ComposeActivity.java revision 26d4d2d9c43c499f458808f050ec73ea3c28dec4
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;
26b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.Fragment;
27b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.FragmentManager;
28b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.FragmentTransaction;
2996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.app.LoaderManager;
306349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.ContentResolver;
3182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.ContentValues;
326349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Context;
3396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.CursorLoader;
3482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.DialogInterface;
356349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Intent;
3696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.Loader;
3782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.pm.ActivityInfo;
387ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereiraimport android.database.Cursor;
396349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.net.Uri;
408e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.os.Bundle;
4182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.Handler;
4282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.HandlerThread;
43f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrookimport android.os.Parcelable;
4482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.provider.BaseColumns;
4546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.Editable;
4682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Html;
4782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Spanned;
48c182762df95fd382faf8e4a25e5cf7783ea10176Paul Westbrookimport android.text.TextUtils;
4982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.TextWatcher;
5046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.util.Rfc822Token;
51c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport android.text.util.Rfc822Tokenizer;
523cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereiraimport android.view.Gravity;
5362d3ec7f251f6f9a96a859a2702916d07f30a04amindypimport android.view.KeyEvent;
54326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.LayoutInflater;
55b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.Menu;
56b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuInflater;
57b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuItem;
588e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View;
598e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View.OnClickListener;
605c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.view.ViewGroup;
61eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereiraimport android.view.inputmethod.BaseInputConnection;
6262d3ec7f251f6f9a96a859a2702916d07f30a04amindypimport android.view.inputmethod.EditorInfo;
63326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.ArrayAdapter;
648e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.widget.Button;
65433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereiraimport android.widget.EditText;
666349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.widget.TextView;
67013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.widget.Toast;
687b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira
69c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport com.android.common.Rfc822Validator;
705c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.ex.chips.RecipientEditTextView;
715c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.mail.R;
7240882430c874ff29890ec6fa31f7649788cbc470mindypimport com.android.mail.compose.AttachmentsView.AttachmentAddedOrDeletedListener;
739932dee248718d2cec993d93b5115973d1389d0aMindy Pereiraimport com.android.mail.compose.AttachmentsView.AttachmentFailureException;
745a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereiraimport com.android.mail.compose.FromAddressSpinner.OnAccountChangedListener;
7530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.compose.QuotedTextView.RespondInlineListener;
7633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereiraimport com.android.mail.providers.Account;
7730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Address;
7830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Attachment;
795ad02918f663bc52522a2505de985df9ef5ea347Mindy Pereiraimport com.android.mail.providers.Folder;
8047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereiraimport com.android.mail.providers.MailAppProvider;
813ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport com.android.mail.providers.Message;
8282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.android.mail.providers.MessageModification;
8392551d057965689f1952faeb06763f0762bc717fMindy Pereiraimport com.android.mail.providers.ReplyFromAccount;
84181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereiraimport com.android.mail.providers.Settings;
8530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.UIProvider;
863ca5bad62c075184920c5e331870280fc6acca16Mindy Pereiraimport com.android.mail.providers.UIProvider.AccountCapabilities;
8712575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereiraimport com.android.mail.providers.UIProvider.DraftType;
88fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereiraimport com.android.mail.ui.MailActivity;
89b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport com.android.mail.ui.WaitFragment;
9062066e47fe69c33b60ed970e46809ba81d044064Mark Weiimport com.android.mail.ui.AttachmentTile.AttachmentPreview;
9192227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrookimport com.android.mail.utils.AccountUtils;
92434f294a3ae17a4f76342af38d6376f672a5d9edMark Weiimport com.android.mail.utils.AttachmentUtils;
93b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
9430e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.LogUtils;
9530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.Utils;
9646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport com.google.common.annotations.VisibleForTesting;
9782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.google.common.collect.Lists;
984a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereiraimport com.google.common.collect.Sets;
998e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira
10062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereiraimport org.json.JSONException;
10162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
1028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.io.UnsupportedEncodingException;
1038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.net.URLDecoder;
10446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.ArrayList;
105bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Arrays;
10646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Collection;
10775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereiraimport java.util.HashMap;
10846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.HashSet;
10946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.List;
1101c078cff1958b29e280100bfa6221103ec46b555Paul Westbrookimport java.util.Map.Entry;
111bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Set;
11282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport java.util.concurrent.ConcurrentHashMap;
11346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
11446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereirapublic class ComposeActivity extends Activity implements OnClickListener, OnNavigationListener,
1155a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira        RespondInlineListener, DialogInterface.OnClickListener, TextWatcher,
11640882430c874ff29890ec6fa31f7649788cbc470mindyp        AttachmentAddedOrDeletedListener, OnAccountChangedListener, LoaderManager.LoaderCallbacks<Cursor>,
11762d3ec7f251f6f9a96a859a2702916d07f30a04amindyp        TextView.OnEditorActionListener {
1186349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    // Identifiers for which type of composition this is
11936bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira    static final int COMPOSE = -1;
12036bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira    static final int REPLY = 0;
12136bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira    static final int REPLY_ALL = 1;
12236bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira    static final int FORWARD = 2;
12336bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira    static final int EDIT_DRAFT = 3;
1246349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
1256349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    // Integer extra holding one of the above compose action
12696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    protected static final String EXTRA_ACTION = "action";
1276349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
128326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira    private static final String EXTRA_SHOW_CC = "showCc";
129326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira    private static final String EXTRA_SHOW_BCC = "showBcc";
130a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira
1318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String UTF8_ENCODING_NAME = "UTF-8";
1328eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
1338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String MAIL_TO = "mailto";
1348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
1358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String EXTRA_SUBJECT = "subject";
1368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
1378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String EXTRA_BODY = "body";
1388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
1399a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira    private static final String EXTRA_FROM_ACCOUNT_STRING = "fromAccountString";
1409a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira
14162066e47fe69c33b60ed970e46809ba81d044064Mark Wei    private static final String EXTRA_ATTACHMENT_PREVIEWS = "attachmentPreviews";
14262066e47fe69c33b60ed970e46809ba81d044064Mark Wei
1438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    // Extra that we can get passed from other activities
1448eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String EXTRA_TO = "to";
1458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String EXTRA_CC = "cc";
1468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    private static final String EXTRA_BCC = "bcc";
1478eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
1488eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    // List of all the fields
1498eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    static final String[] ALL_EXTRAS = { EXTRA_SUBJECT, EXTRA_BODY, EXTRA_TO, EXTRA_CC, EXTRA_BCC };
1508eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
15182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private static SendOrSaveCallback sTestSendOrSaveCallback = null;
15282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // Map containing information about requests to create new messages, and the id of the
15382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // messages that were the result of those requests.
15482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    //
15582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // This map is used when the activity that initiated the save a of a new message, is killed
15682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // before the save has completed (and when we know the id of the newly created message).  When
15782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // a save is completed, the service that is running in the background, will update the map
15882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    //
15982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // When a new ComposeActivity instance is created, it will attempt to use the information in
16082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // the previously instantiated map.  If ComposeActivity.onCreate() is called, with a bundle
16182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // (restoring data from a previous instance), and the map hasn't been created, we will attempt
16282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // to populate the map with data stored in shared preferences.
16382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private static ConcurrentHashMap<Integer, Long> sRequestMessageIdMap = null;
16482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // Key used to store the above map
16582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private static final String CACHED_MESSAGE_REQUEST_IDS_KEY = "cache-message-request-ids";
1666349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    /**
1676349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * Notifies the {@code Activity} that the caller is an Email
1686349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * {@code Activity}, so that the back behavior may be modified accordingly.
1696349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     *
1706349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * @see #onAppUpPressed
1716349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     */
172daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook    public static final String EXTRA_FROM_EMAIL_TASK = "fromemail";
1736349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
174e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public static final String EXTRA_ATTACHMENTS = "attachments";
175f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook
1763ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    //  If this is a reply/forward then this extra will hold the original message
17736bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira    private static final String EXTRA_IN_REFERENCE_TO_MESSAGE = "in-reference-to-message";
178b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira    // If this is a reply/forward then this extra will hold a uri we must query
179b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira    // to get the original message.
180b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira    protected static final String EXTRA_IN_REFERENCE_TO_MESSAGE_URI = "in-reference-to-message-uri";
181434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei    // If this is an action to edit an existing draft message, this extra will hold the
182bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    // draft message
183bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    private static final String ORIGINAL_DRAFT_MESSAGE = "original-draft-message";
1844a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    private static final String END_TOKEN = ", ";
185b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    private static final String LOG_TAG = LogTag.getLogTag();
186013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    // Request numbers for activities we start
187013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    private static final int RESULT_PICK_ATTACHMENT = 1;
188013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    private static final int RESULT_CREATE_ACCOUNT = 2;
1898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    // TODO(mindyp) set mime-type for auto send?
190e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public static final String AUTO_SEND_ACTION = "com.android.mail.action.AUTO_SEND";
1918eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
192e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private static final String EXTRA_SELECTED_REPLY_FROM_ACCOUNT = "replyFromAccount";
193e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private static final String EXTRA_REQUEST_ID = "requestId";
194e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private static final String EXTRA_FOCUS_SELECTION_START = "focusSelectionStart";
195e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private static final String EXTRA_FOCUS_SELECTION_END = null;
196e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private static final String EXTRA_MESSAGE = "extraMessage";
19796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    private static final int REFERENCE_MESSAGE_LOADER = 0;
198b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private static final int LOADER_ACCOUNT_CURSOR = 1;
19947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira    private static final String EXTRA_SELECTED_ACCOUNT = "selectedAccount";
200b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private static final String TAG_WAIT = "wait-fragment";
2012db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira    private static final String MIME_TYPE_PHOTO = "image/*";
2022db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira    private static final String MIME_TYPE_VIDEO = "video/*";
2038e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira
20482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
20582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * A single thread for running tasks in the background.
20682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
20782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private Handler mSendSaveTaskHandler = null;
208c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira    private RecipientEditTextView mTo;
209c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira    private RecipientEditTextView mCc;
210c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira    private RecipientEditTextView mBcc;
2118e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    private Button mCcBccButton;
2128e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    private CcBccView mCcBccView;
2137b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira    private AttachmentsView mAttachmentsView;
21433fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira    private Account mAccount;
21592551d057965689f1952faeb06763f0762bc717fMindy Pereira    private ReplyFromAccount mReplyFromAccount;
216181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    private Settings mCachedSettings;
21782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private Rfc822Validator mValidator;
2186349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    private TextView mSubject;
2196349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
220326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    private ComposeModeAdapter mComposeModeAdapter;
221326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    private int mComposeMode = -1;
22246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    private boolean mForward;
22346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    private String mRecipient;
22446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    private QuotedTextView mQuotedTextView;
225433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira    private EditText mBodyView;
2261a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira    private View mFromStatic;
2272eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira    private TextView mFromStaticText;
228eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    private View mFromSpinnerWrapper;
2291883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira    @VisibleForTesting
2301883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira    protected FromAddressSpinner mFromSpinner;
231013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    private boolean mAddingAttachment;
232eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    private boolean mAttachmentsChanged;
23382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private boolean mTextChanged;
23482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private boolean mReplyFromChanged;
23582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private MenuItem mSave;
23682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private MenuItem mSend;
23782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private AlertDialog mRecipientErrorDialog;
238eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    private AlertDialog mSendConfirmDialog;
239b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira    @VisibleForTesting
240b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira    protected Message mRefMessage;
2417ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira    private long mDraftId = UIProvider.INVALID_MESSAGE_ID;
2427ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira    private Message mDraft;
2437ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira    private Object mDraftLock = new Object();
24493b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp    private View mPhotoAttachmentsButton;
24593b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp    private View mVideoAttachmentsButton;
2463ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
247326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    /**
248daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook     * Boolean indicating whether ComposeActivity was launched from a Gmail controlled view.
249daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook     */
250daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook    private boolean mLaunchedFromEmail = false;
251cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira    private RecipientTextWatcher mToListener;
252cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira    private RecipientTextWatcher mCcListener;
253cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira    private RecipientTextWatcher mBccListener;
254b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira    private Uri mRefMessageUri;
255b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private Bundle mSavedInstanceState;
256daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook
257daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook
258daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook    /**
259326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira     * Can be called from a non-UI thread.
260326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira     */
2613ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public static void editDraft(Context launcher, Account account, Message message) {
262bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        launch(launcher, account, message, EDIT_DRAFT);
263326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    }
264326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
2656349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    /**
2666349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * Can be called from a non-UI thread.
2676349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     */
26833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira    public static void compose(Context launcher, Account account) {
2696349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        launch(launcher, account, null, COMPOSE);
2706349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    }
2716349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
2726349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    /**
2736349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * Can be called from a non-UI thread.
2746349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     */
2753ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public static void reply(Context launcher, Account account, Message message) {
2763ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        launch(launcher, account, message, REPLY);
2776349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    }
2786349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
2796349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    /**
2806349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * Can be called from a non-UI thread.
2816349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     */
2823ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public static void replyAll(Context launcher, Account account, Message message) {
2833ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        launch(launcher, account, message, REPLY_ALL);
2846349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    }
2856349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
2866349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    /**
2876349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     * Can be called from a non-UI thread.
2886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira     */
2893ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public static void forward(Context launcher, Account account, Message message) {
2903ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        launch(launcher, account, message, FORWARD);
2916349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    }
2926349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
2933ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    private static void launch(Context launcher, Account account, Message message, int action) {
2946349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        Intent intent = new Intent(launcher, ComposeActivity.class);
2956349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        intent.putExtra(EXTRA_FROM_EMAIL_TASK, true);
2966349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        intent.putExtra(EXTRA_ACTION, action);
2976349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        intent.putExtra(Utils.EXTRA_ACCOUNT, account);
298bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (action == EDIT_DRAFT) {
299bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook            intent.putExtra(ORIGINAL_DRAFT_MESSAGE, message);
300bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        } else {
301bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook            intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE, message);
302bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
3036349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        launcher.startActivity(intent);
3046349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    }
3058e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira
3068e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    @Override
3078e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    public void onCreate(Bundle savedInstanceState) {
3088e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        super.onCreate(savedInstanceState);
3098e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        setContentView(R.layout.compose);
310b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        mSavedInstanceState = savedInstanceState;
311b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        checkValidAccounts();
312b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    }
313b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira
314b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private void finishCreate() {
315b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        Bundle savedInstanceState = mSavedInstanceState;
31646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        findViews();
317818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        Intent intent = getIntent();
318e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        Message message;
31962066e47fe69c33b60ed970e46809ba81d044064Mark Wei        ArrayList<AttachmentPreview> previews;
32071c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira        boolean showQuotedText = false;
321e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        int action;
32247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        // Check for any of the possibly supplied accounts.;
32347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        Account account = null;
324f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira        if (hadSavedInstanceStateMessage(savedInstanceState)) {
325e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            action = savedInstanceState.getInt(EXTRA_ACTION, COMPOSE);
326e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            account = savedInstanceState.getParcelable(Utils.EXTRA_ACCOUNT);
327e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            message = (Message) savedInstanceState.getParcelable(EXTRA_MESSAGE);
32862066e47fe69c33b60ed970e46809ba81d044064Mark Wei
32962066e47fe69c33b60ed970e46809ba81d044064Mark Wei            previews = savedInstanceState.getParcelableArrayList(EXTRA_ATTACHMENT_PREVIEWS);
330e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            mRefMessage = (Message) savedInstanceState.getParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE);
331e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        } else {
33247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            account = obtainAccount(intent);
333e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            action = intent.getIntExtra(EXTRA_ACTION, COMPOSE);
334e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            // Initialize the message from the message in the intent
335e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            message = (Message) intent.getParcelableExtra(ORIGINAL_DRAFT_MESSAGE);
33662066e47fe69c33b60ed970e46809ba81d044064Mark Wei            previews = intent.getParcelableArrayListExtra(EXTRA_ATTACHMENT_PREVIEWS);
337e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            mRefMessage = (Message) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE);
338b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira            mRefMessageUri = (Uri) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI);
339e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
34062066e47fe69c33b60ed970e46809ba81d044064Mark Wei        mAttachmentsView.setAttachmentPreviews(previews);
34192227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook
34292227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook        setAccount(account);
343818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        if (mAccount == null) {
344818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira            return;
345818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        }
346bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
347daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        if (intent.getBooleanExtra(EXTRA_FROM_EMAIL_TASK, false)) {
348daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            mLaunchedFromEmail = true;
349daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        } else if (Intent.ACTION_SEND.equals(intent.getAction())) {
350daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            final Uri dataUri = intent.getData();
351daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            if (dataUri != null) {
352daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook                final String dataScheme = intent.getData().getScheme();
353daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook                final String accountScheme = mAccount.composeIntentUri.getScheme();
354daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook                mLaunchedFromEmail = TextUtils.equals(dataScheme, accountScheme);
355daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            }
356daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        }
357daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook
35896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        if (mRefMessageUri != null) {
35996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            // We have a referenced message that we must look up.
36096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            getLoaderManager().initLoader(REFERENCE_MESSAGE_LOADER, null, this);
36196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            return;
36296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        } else if (message != null && action != EDIT_DRAFT) {
363e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            initFromDraftMessage(message);
364e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            initQuotedTextFromRefMessage(mRefMessage, action);
365a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira            showCcBcc(savedInstanceState);
36671c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira            showQuotedText = message.appendRefMessageContent;
367e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        } else if (action == EDIT_DRAFT) {
368e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            initFromDraftMessage(message);
369ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            boolean showBcc = !TextUtils.isEmpty(message.bcc);
370ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            boolean showCc = showBcc || !TextUtils.isEmpty(message.cc);
371ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            mCcBccView.show(false, showCc, showBcc);
372bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook            // Update the action to the draft type of the previous draft
373bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook            switch (message.draftType) {
374bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                case UIProvider.DraftType.REPLY:
375bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    action = REPLY;
376bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    break;
377bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                case UIProvider.DraftType.REPLY_ALL:
378bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    action = REPLY_ALL;
379bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    break;
380bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                case UIProvider.DraftType.FORWARD:
381bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    action = FORWARD;
382bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    break;
383bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                case UIProvider.DraftType.COMPOSE:
384bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                default:
385bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    action = COMPOSE;
386bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook                    break;
387bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook            }
388e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            initQuotedTextFromRefMessage(mRefMessage, action);
38971c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira            showQuotedText = message.appendRefMessageContent;
390e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        } else if ((action == REPLY || action == REPLY_ALL || action == FORWARD)) {
391e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            if (mRefMessage != null) {
392e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                initFromRefMessage(action, mAccount.name);
39371c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira                showQuotedText = true;
394e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            }
3958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        } else {
3968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            initFromExtras(intent);
397bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
39896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        finishSetup(action, intent, savedInstanceState, showQuotedText);
39996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    }
400bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
401b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private void checkValidAccounts() {
402b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        mAccounts = AccountUtils.getAccounts(this);
403b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (mAccounts == null || mAccounts.length == 0) {
404b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            final Intent noAccountIntent = MailAppProvider.getNoAccountIntent(this);
405b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            if (noAccountIntent != null) {
406b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                startActivityForResult(noAccountIntent, RESULT_CREATE_ACCOUNT);
407b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            }
408b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        } else {
40926d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp            // If none of the accounts are syncing, setup a watcher.
410b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            boolean anySyncing = false;
411b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            for (Account a : mAccounts) {
412b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                if (a.isAccountIntialized()) {
413b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    anySyncing = true;
414b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    break;
415b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                }
416b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            }
417b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            if (!anySyncing) {
418b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                // There are accounts, but none are sync'd, which is just like having no accounts.
419b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                mAccounts = null;
420b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);
421b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                return;
422b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            }
423b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            finishCreate();
424b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        }
425b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    }
426b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira
42747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira    private Account obtainAccount(Intent intent) {
42847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        Account account = null;
42947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        Object accountExtra = null;
43047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        if (intent != null && intent.getExtras() != null) {
43147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            accountExtra = intent.getExtras().get(Utils.EXTRA_ACCOUNT);
43247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            if (accountExtra instanceof Account) {
43347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                return (Account) accountExtra;
4347ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp            } else if (accountExtra instanceof String) {
4357ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp                // This is the Account attached to the widget compose intent.
4367ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp                account = Account.newinstance((String)accountExtra);
4377ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp                if (account != null) {
4387ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp                    return account;
4397ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp                }
44047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            }
44147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            accountExtra = intent.getStringExtra(EXTRA_SELECTED_ACCOUNT);
44247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        }
44347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        if (account == null) {
44447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            final String lastAccountUri = MailAppProvider.getInstance().getLastSentFromAccount();
44547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            if (!TextUtils.isEmpty(lastAccountUri)) {
44647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                accountExtra = Uri.parse(lastAccountUri);
44747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            }
44847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        }
449b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (mAccounts != null && mAccounts.length > 0) {
45047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            if (accountExtra instanceof String && !TextUtils.isEmpty((String) accountExtra)) {
45147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                // For backwards compatibility, we need to check account
45247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                // names.
453b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                for (Account a : mAccounts) {
45447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                    if (a.name.equals(accountExtra)) {
45547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                        account = a;
45647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                    }
45747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                }
45847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            } else if (accountExtra instanceof Uri) {
45947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                // The uri of the last viewed account is what is stored in
46047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                // the current code base.
461b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                for (Account a : mAccounts) {
46247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                    if (a.uri.equals(accountExtra)) {
46347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                        account = a;
46447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                    }
46547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                }
466b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            }
467b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            if (account == null) {
468b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                account = mAccounts[0];
46947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira            }
47047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        }
47147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira        return account;
47247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira    }
47347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira
47496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    private void finishSetup(int action, Intent intent, Bundle savedInstanceState,
47596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            boolean showQuotedText) {
476bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (action == COMPOSE) {
477eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            mQuotedTextView.setVisibility(View.GONE);
47846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        }
479818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        initRecipients();
480f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira        // Don't bother with the intent if we have procured a message from the
481f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira        // intent already.
482f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira        if (!hadSavedInstanceStateMessage(savedInstanceState)) {
483f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira            initAttachmentsFromIntent(intent);
484f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira        }
4851a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira        initActionBar(action);
486e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        initFromSpinner(savedInstanceState != null ? savedInstanceState : intent.getExtras(),
487e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                action);
48875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        initChangeListeners();
489433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        setFocus(action);
490326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        updateHideOrShowCcBcc();
49171c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira        updateHideOrShowQuotedText(showQuotedText);
49271c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira    }
49371c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira
494f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira    private boolean hadSavedInstanceStateMessage(Bundle savedInstanceState) {
495f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira        return savedInstanceState != null && savedInstanceState.containsKey(EXTRA_MESSAGE);
496f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira    }
497f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira
49871c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira    private void updateHideOrShowQuotedText(boolean showQuotedText) {
49971c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira        mQuotedTextView.updateCheckedState(showQuotedText);
50040882430c874ff29890ec6fa31f7649788cbc470mindyp        mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0);
501433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira    }
502433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira
503433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira    private void setFocus(int action) {
504433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        if (action == EDIT_DRAFT) {
505433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            int type = mDraft.draftType;
506433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            switch (type) {
507433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                case UIProvider.DraftType.COMPOSE:
508433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                case UIProvider.DraftType.FORWARD:
509433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                    action = COMPOSE;
510433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                    break;
511433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                case UIProvider.DraftType.REPLY:
512433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                case UIProvider.DraftType.REPLY_ALL:
513433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                default:
514433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                    action = REPLY;
515433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                    break;
516433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            }
517433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        }
518433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        switch (action) {
519433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            case FORWARD:
520433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            case COMPOSE:
521433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                mTo.requestFocus();
522433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                break;
523433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            case REPLY:
524433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            case REPLY_ALL:
525433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            default:
526433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                focusBody();
527433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                break;
528433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        }
529433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira    }
530433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira
531433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira    /**
532433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira     * Focus the body of the message.
533433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira     */
534433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira    public void focusBody() {
535433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        mBodyView.requestFocus();
536433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        int length = mBodyView.getText().length();
537433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira
538433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        int signatureStartPos = getSignatureStartPosition(
539433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                mSignature, mBodyView.getText().toString());
540433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        if (signatureStartPos > -1) {
541433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            // In case the user deleted the newlines...
542433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            mBodyView.setSelection(signatureStartPos);
5438743cfca851058d50385951b111dd903b1fa6c5amindyp        } else if (length >= 0) {
544433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            // Move cursor to the end.
545433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            mBodyView.setSelection(length);
546433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        }
5471a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira    }
5481a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira
5491a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira    @Override
5501a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira    protected void onResume() {
5511a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira        super.onResume();
5521a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira        // Update the from spinner as other accounts
5531a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira        // may now be available.
554818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        if (mFromSpinner != null && mAccount != null) {
555b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            mFromSpinner.asyncInitFromSpinner(mComposeMode, mAccount, mAccounts);
556818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        }
5571a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira    }
5581a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira
559eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    @Override
560eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    protected void onPause() {
561eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        super.onPause();
562eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
563eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        if (mSendConfirmDialog != null) {
564eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            mSendConfirmDialog.dismiss();
565eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        }
566eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        if (mRecipientErrorDialog != null) {
567eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            mRecipientErrorDialog.dismiss();
568eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        }
569a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira        // When the user exits the compose view, see if this draft needs saving.
570a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira        if (isFinishing()) {
571a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira            saveIfNeeded();
572a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira        }
573eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
574eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
575eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    @Override
576eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    protected final void onActivityResult(int request, int result, Intent data) {
577b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (request == RESULT_PICK_ATTACHMENT && result == RESULT_OK) {
578eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            addAttachmentAndUpdateView(data);
579b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            mAddingAttachment = false;
580b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        } else if (request == RESULT_CREATE_ACCOUNT) {
581b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                // We were waiting for the user to create an account
582b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            if (result != RESULT_OK) {
583b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                finish();
584b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            } else {
585b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                // Watch for accounts to show up!
586b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                // restart the loader to get the updated list of accounts
587b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);
588b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                showWaitFragment(null);
589b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            }
590eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        }
591eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
592eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
593eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    @Override
594e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    public final void onRestoreInstanceState(Bundle savedInstanceState) {
595e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        super.onRestoreInstanceState(savedInstanceState);
596e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (savedInstanceState != null) {
597e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            if (savedInstanceState.containsKey(EXTRA_FOCUS_SELECTION_START)) {
598e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                int selectionStart = savedInstanceState.getInt(EXTRA_FOCUS_SELECTION_START);
599e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                int selectionEnd = savedInstanceState.getInt(EXTRA_FOCUS_SELECTION_END);
600e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                // There should be a focus and it should be an EditText since we
601e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                // only save these extras if these conditions are true.
602e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                EditText focusEditText = (EditText) getCurrentFocus();
603e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                final int length = focusEditText.getText().length();
604e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                if (selectionStart < length && selectionEnd < length) {
605e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                    focusEditText.setSelection(selectionStart, selectionEnd);
606e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                }
607e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            }
608e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
609e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    }
610e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
611e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    @Override
612eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    public final void onSaveInstanceState(Bundle state) {
613eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        super.onSaveInstanceState(state);
614b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        // We have no accounts so there is nothing to compose, and therefore, nothing to save.
615b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (mAccounts == null || mAccounts.length == 0) {
616b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            return;
617b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        }
618e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        // The framework is happy to save and restore the selection but only if it also saves and
619e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        // restores the contents of the edit text. That's a lot of text to put in a bundle so we do
620e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        // this manually.
621e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        View focus = getCurrentFocus();
622e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (focus != null && focus instanceof EditText) {
623e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            EditText focusEditText = (EditText) focus;
624e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putInt(EXTRA_FOCUS_SELECTION_START, focusEditText.getSelectionStart());
625e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putInt(EXTRA_FOCUS_SELECTION_END, focusEditText.getSelectionEnd());
626e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
6276273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook
6286273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook        final List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts();
629151f1ad1613ecac0207144472872440517172b5aPaul Westbrook        final int selectedPos = mFromSpinner.getSelectedItemPosition();
630d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira        final ReplyFromAccount selectedReplyFromAccount = (replyFromAccounts != null
631d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira                && replyFromAccounts.size() > 0 && replyFromAccounts.size() > selectedPos) ?
632d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira                        replyFromAccounts.get(selectedPos) : null;
633e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (selectedReplyFromAccount != null) {
634e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT, selectedReplyFromAccount.serialize()
635e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                    .toString());
636e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putParcelable(Utils.EXTRA_ACCOUNT, selectedReplyFromAccount.account);
637e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        } else {
638e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putParcelable(Utils.EXTRA_ACCOUNT, mAccount);
639e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
640eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
641e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (mDraftId == UIProvider.INVALID_MESSAGE_ID && mRequestId !=0) {
642e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            // We don't have a draft id, and we have a request id,
643e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            // save the request id.
644e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putInt(EXTRA_REQUEST_ID, mRequestId);
645e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
646e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
647e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        // We want to restore the current mode after a pause
648e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        // or rotation.
649e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        int mode = getMode();
650e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        state.putInt(EXTRA_ACTION, mode);
651e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
652e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        Message message = createMessage(selectedReplyFromAccount, mode);
653e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        state.putParcelable(EXTRA_MESSAGE, message);
654e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
655e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (mRefMessage != null) {
656e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            state.putParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE, mRefMessage);
657e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
658326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        state.putBoolean(EXTRA_SHOW_CC, mCcBccView.isCcVisible());
659326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        state.putBoolean(EXTRA_SHOW_BCC, mCcBccView.isBccVisible());
66062066e47fe69c33b60ed970e46809ba81d044064Mark Wei
66162066e47fe69c33b60ed970e46809ba81d044064Mark Wei        state.putParcelableArrayList(
66262066e47fe69c33b60ed970e46809ba81d044064Mark Wei                EXTRA_ATTACHMENT_PREVIEWS, mAttachmentsView.getAttachmentPreviews());
663e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    }
664e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
665e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private int getMode() {
666e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        int mode = ComposeActivity.COMPOSE;
667e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        ActionBar actionBar = getActionBar();
668e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        if (actionBar != null
669e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira                && actionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST) {
670e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            mode = actionBar.getSelectedNavigationIndex();
671e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
672e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        return mode;
673e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    }
674e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
675e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private Message createMessage(ReplyFromAccount selectedReplyFromAccount, int mode) {
676e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        Message message = new Message();
677e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.id = UIProvider.INVALID_MESSAGE_ID;
678d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang        message.serverId = null;
679e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.uri = null;
680e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.conversationUri = null;
681e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.subject = mSubject.getText().toString();
682e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.snippet = null;
6831eedc7520600a315afba4fc114a9fc5bf1adacd7Mindy Pereira        message.from = selectedReplyFromAccount != null ? selectedReplyFromAccount.address
684b67aa8f5975082434dc6b8ebeedf2f1333dbf86dMindy Pereira                : mAccount != null ? mAccount.name : null;
6853c9115813343861a44133b805fb9f55512d20948Mindy Pereira        message.to = formatSenders(mTo.getText().toString());
6863c9115813343861a44133b805fb9f55512d20948Mindy Pereira        message.cc = formatSenders(mCc.getText().toString());
6873c9115813343861a44133b805fb9f55512d20948Mindy Pereira        message.bcc = formatSenders(mBcc.getText().toString());
688e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.replyTo = null;
689e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.dateReceivedMs = 0;
690e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        String htmlBody = Html.toHtml(mBodyView.getText());
691e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        StringBuilder fullBody = new StringBuilder(htmlBody);
692e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.bodyHtml = fullBody.toString();
693e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.bodyText = mBodyView.getText().toString();
694e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.embedsExternalResources = false;
695e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.refMessageId = mRefMessage != null ? mRefMessage.uri.toString() : null;
696d2bef8b371784d95f60dd3f89aa0ac3557c945efMindy Pereira        message.draftType = getDraftType(mode);
697e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.appendRefMessageContent = mQuotedTextView.getQuotedTextIfIncluded() != null;
698e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        ArrayList<Attachment> attachments = mAttachmentsView.getAttachments();
699e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.hasAttachments = attachments != null && attachments.size() > 0;
700e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.attachmentListUri = null;
701e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.messageFlags = 0;
702e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.saveUri = null;
703e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.sendUri = null;
704e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.alwaysShowImages = false;
705e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.attachmentsJson = Attachment.toJSONArray(attachments);
706e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        CharSequence quotedText = mQuotedTextView.getQuotedText();
707e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.quotedTextOffset = !TextUtils.isEmpty(quotedText) ? QuotedTextView
708e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                .getQuotedTextOffset(quotedText.toString()) : -1;
709e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        message.accountUri = null;
710e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        return message;
711eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
712eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
7133c9115813343861a44133b805fb9f55512d20948Mindy Pereira    private String formatSenders(String string) {
7143c9115813343861a44133b805fb9f55512d20948Mindy Pereira        if (!TextUtils.isEmpty(string) && string.charAt(string.length() - 1) == ',') {
7153c9115813343861a44133b805fb9f55512d20948Mindy Pereira            return string.substring(0, string.length() - 1);
7163c9115813343861a44133b805fb9f55512d20948Mindy Pereira        }
7173c9115813343861a44133b805fb9f55512d20948Mindy Pereira        return string;
7183c9115813343861a44133b805fb9f55512d20948Mindy Pereira    }
7193c9115813343861a44133b805fb9f55512d20948Mindy Pereira
720818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira    @VisibleForTesting
721818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira    void setAccount(Account account) {
722bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira        if (account == null) {
723bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira            return;
724bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira        }
72523e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira        if (!account.equals(mAccount)) {
72623e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira            mAccount = account;
727b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook            mCachedSettings = mAccount.settings;
728b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook            appendSignature();
72923e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira        }
730fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira        if (mAccount != null) {
731fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira            MailActivity.setForegroundNdef(MailActivity.getMailtoNdef(mAccount.name));
732fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira        }
733818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira    }
734818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira
735e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private void initFromSpinner(Bundle bundle, int action) {
7369a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira        String accountString = null;
737e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (action == EDIT_DRAFT && mDraft.draftType == UIProvider.DraftType.COMPOSE) {
73862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            action = COMPOSE;
73962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
740b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        mFromSpinner.asyncInitFromSpinner(action, mAccount, mAccounts);
7419a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira        if (bundle != null) {
7429a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira            if (bundle.containsKey(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)) {
7439a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira                mReplyFromAccount = ReplyFromAccount.deserialize(mAccount,
7449a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira                        bundle.getString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT));
7459a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira            } else if (bundle.containsKey(EXTRA_FROM_ACCOUNT_STRING)) {
7469a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira                accountString = bundle.getString(EXTRA_FROM_ACCOUNT_STRING);
7479a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira                mReplyFromAccount = mFromSpinner.getMatchingReplyFromAccount(accountString);
7489a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira            }
749e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        }
750e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (mReplyFromAccount == null) {
751e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            if (mDraft != null) {
752e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                mReplyFromAccount = getReplyFromAccountFromDraft(mAccount, mDraft);
753e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            } else if (mRefMessage != null) {
754e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira                mReplyFromAccount = getReplyFromAccountForReply(mAccount, mRefMessage);
755e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira            }
75662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
75762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        if (mReplyFromAccount == null) {
75862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            mReplyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name,
759cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira                    mAccount.name, mAccount.name, true, false);
76062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
7619a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira
76262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        mFromSpinner.setCurrentAccount(mReplyFromAccount);
7639a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira
76462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        if (mFromSpinner.getCount() > 1) {
765a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira            // If there is only 1 account, just show that account.
766a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira            // Otherwise, give the user the ability to choose which account to
76762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            // send mail from / save drafts to.
76862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            mFromStatic.setVisibility(View.GONE);
769a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira            mFromStaticText.setText(mAccount.name);
77062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            mFromSpinnerWrapper.setVisibility(View.VISIBLE);
771a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira        } else {
772a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira            mFromStatic.setVisibility(View.VISIBLE);
773a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira            mFromStaticText.setText(mAccount.name);
774a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira            mFromSpinnerWrapper.setVisibility(View.GONE);
775a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira        }
77646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
77746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
77862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    private ReplyFromAccount getReplyFromAccountForReply(Account account, Message refMessage) {
77962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        if (refMessage.accountUri != null) {
78062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            // This must be from combined inbox.
78162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts();
78262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            for (ReplyFromAccount from : replyFromAccounts) {
78362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                if (from.account.uri.equals(refMessage.accountUri)) {
78462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                    return from;
78562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                }
78662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            }
78762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            return null;
78862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        } else {
78962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            return getReplyFromAccount(account, refMessage);
79062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
79162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    }
79262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
79362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    /**
79462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * Given an account and which email address the message was sent to,
79562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * return who the message should be sent from.
79662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * @param account Account in which the message arrived.
79762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * @param sentTo Email address to which the message was sent.
79862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * @return the address from which to reply.
79962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     */
80062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    public ReplyFromAccount getReplyFromAccount(Account account, Message refMessage) {
80162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        // First see if we are supposed to use the default address or
80262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        // the address it was sentTo.
803326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        if (mCachedSettings.forceReplyFromDefault) {
80462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            return getDefaultReplyFromAccount(account);
80562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        } else {
80689bae5713b830ec1182073de22c3091d3613ac3eMindy Pereira            // If we aren't explicitly told which account to look for, look at
80762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            // all the message recipients and find one that matches
80862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            // a custom from or account.
80962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            List<String> allRecipients = new ArrayList<String>();
8105ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp            allRecipients.addAll(Arrays.asList(refMessage.getToAddresses()));
8115ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp            allRecipients.addAll(Arrays.asList(refMessage.getCcAddresses()));
81262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            return getMatchingRecipient(account, allRecipients);
81362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
81462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    }
81562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
81662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    /**
81762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * Compare all the recipients of an email to the current account and all
81862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * custom addresses associated with that account. Return the match if there
81962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     * is one, or the default account if there isn't.
82062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira     */
82162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    protected ReplyFromAccount getMatchingRecipient(Account account, List<String> sentTo) {
82262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        // Tokenize the list and place in a hashmap.
82362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        ReplyFromAccount matchingReplyFrom = null;
82462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        Rfc822Token[] tokens;
82562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        HashSet<String> recipientsMap = new HashSet<String>();
82662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        for (String address : sentTo) {
82762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            tokens = Rfc822Tokenizer.tokenize(address);
82862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            for (int i = 0; i < tokens.length; i++) {
82962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                recipientsMap.add(tokens[i].getAddress());
83062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            }
83162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
83262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
83362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        int matchingAddressCount = 0;
83462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        List<ReplyFromAccount> customFroms;
8351617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang        customFroms = account.getReplyFroms();
8361617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang        if (customFroms != null) {
8371617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang            for (ReplyFromAccount entry : customFroms) {
8381617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang                if (recipientsMap.contains(entry.address)) {
8391617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang                    matchingReplyFrom = entry;
8401617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang                    matchingAddressCount++;
84162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                }
84262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            }
84362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
84462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        if (matchingAddressCount > 1) {
84562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            matchingReplyFrom = getDefaultReplyFromAccount(account);
84662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
84762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        return matchingReplyFrom;
84862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    }
84962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
85062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    private ReplyFromAccount getDefaultReplyFromAccount(Account account) {
85162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts();
85262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        for (ReplyFromAccount from : replyFromAccounts) {
85362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            if (from.isDefault) {
85462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                return from;
85562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            }
85662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
857cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira        return new ReplyFromAccount(account, account.uri, account.name, account.name, account.name,
858cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira                true, false);
85962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    }
86062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
861e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private ReplyFromAccount getReplyFromAccountFromDraft(Account account, Message msg) {
862e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        String sender = msg.from;
86362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        ReplyFromAccount replyFromAccount = null;
86462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts();
86562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        if (TextUtils.equals(account.name, sender)) {
86662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            replyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name,
867cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira                    mAccount.name, mAccount.name, true, false);
86862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        } else {
86962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            for (ReplyFromAccount fromAccount : replyFromAccounts) {
87062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                if (TextUtils.equals(fromAccount.name, sender)) {
87162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                    replyFromAccount = fromAccount;
87262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                    break;
87362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira                }
87462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            }
87562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        }
87662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        return replyFromAccount;
87762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    }
87862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira
87946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    private void findViews() {
880b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        findViewById(R.id.compose).setVisibility(View.VISIBLE);
881a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        mCcBccButton = (Button) findViewById(R.id.add_cc_bcc);
8828e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        if (mCcBccButton != null) {
8838e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira            mCcBccButton.setOnClickListener(this);
8848e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        }
8858e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        mCcBccView = (CcBccView) findViewById(R.id.cc_bcc_wrapper);
8867b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira        mAttachmentsView = (AttachmentsView)findViewById(R.id.attachments);
88793b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp        mPhotoAttachmentsButton = findViewById(R.id.add_photo_attachment);
888cd0b0b950efebfc3964334067747b97e61c4f027mindyp        if (mPhotoAttachmentsButton != null) {
889cd0b0b950efebfc3964334067747b97e61c4f027mindyp            mPhotoAttachmentsButton.setOnClickListener(this);
890cd0b0b950efebfc3964334067747b97e61c4f027mindyp        }
89193b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp        mVideoAttachmentsButton = findViewById(R.id.add_video_attachment);
892cd0b0b950efebfc3964334067747b97e61c4f027mindyp        if (mVideoAttachmentsButton != null) {
893cd0b0b950efebfc3964334067747b97e61c4f027mindyp            mVideoAttachmentsButton.setOnClickListener(this);
894cd0b0b950efebfc3964334067747b97e61c4f027mindyp        }
895818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        mTo = (RecipientEditTextView) findViewById(R.id.to);
896818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        mCc = (RecipientEditTextView) findViewById(R.id.cc);
897818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        mBcc = (RecipientEditTextView) findViewById(R.id.bcc);
89882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        // TODO: add special chips text change watchers before adding
89982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        // this as a text changed watcher to the to, cc, bcc fields.
9006349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        mSubject = (TextView) findViewById(R.id.subject);
90162d3ec7f251f6f9a96a859a2702916d07f30a04amindyp        mSubject.setOnEditorActionListener(this);
90246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        mQuotedTextView = (QuotedTextView) findViewById(R.id.quoted_text_view);
90346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        mQuotedTextView.setRespondInlineListener(this);
904433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        mBodyView = (EditText) findViewById(R.id.body);
9051a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira        mFromStatic = findViewById(R.id.static_from_content);
9062eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira        mFromStaticText = (TextView) findViewById(R.id.from_account_name);
907eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        mFromSpinnerWrapper = findViewById(R.id.spinner_from_content);
9085a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira        mFromSpinner = (FromAddressSpinner) findViewById(R.id.from_picker);
909326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    }
910326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
91162d3ec7f251f6f9a96a859a2702916d07f30a04amindyp    @Override
91262d3ec7f251f6f9a96a859a2702916d07f30a04amindyp    public boolean onEditorAction(TextView view, int action, KeyEvent keyEvent) {
91362d3ec7f251f6f9a96a859a2702916d07f30a04amindyp        if (action == EditorInfo.IME_ACTION_DONE) {
91462d3ec7f251f6f9a96a859a2702916d07f30a04amindyp            focusBody();
91562d3ec7f251f6f9a96a859a2702916d07f30a04amindyp            return true;
91662d3ec7f251f6f9a96a859a2702916d07f30a04amindyp        }
91762d3ec7f251f6f9a96a859a2702916d07f30a04amindyp        return false;
91862d3ec7f251f6f9a96a859a2702916d07f30a04amindyp    }
91962d3ec7f251f6f9a96a859a2702916d07f30a04amindyp
920e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    protected TextView getBody() {
921e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        return mBodyView;
922e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    }
923e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira
924e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    @VisibleForTesting
925e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public Account getFromAccount() {
926e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        return mReplyFromAccount != null && mReplyFromAccount.account != null ?
927e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira                mReplyFromAccount.account : mAccount;
928e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    }
929e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira
930cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira    private void clearChangeListeners() {
931cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mSubject.removeTextChangedListener(this);
932cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mBodyView.removeTextChangedListener(this);
933cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mTo.removeTextChangedListener(mToListener);
934cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mCc.removeTextChangedListener(mCcListener);
935cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mBcc.removeTextChangedListener(mBccListener);
936cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mFromSpinner.setOnAccountChangedListener(null);
937cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mAttachmentsView.setAttachmentChangesListener(null);
938cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira    }
939cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira
94075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    // Now that the message has been initialized from any existing draft or
94175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    // ref message data, set up listeners for any changes that occur to the
94275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    // message.
94375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    private void initChangeListeners() {
94475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        mSubject.addTextChangedListener(this);
94575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        mBodyView.addTextChangedListener(this);
946cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        if (mToListener == null) {
947cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira            mToListener = new RecipientTextWatcher(mTo, this);
948cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        }
949cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mTo.addTextChangedListener(mToListener);
950cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        if (mCcListener == null) {
951cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira            mCcListener = new RecipientTextWatcher(mCc, this);
952cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        }
953cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mCc.addTextChangedListener(mCcListener);
954cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        if (mBccListener == null) {
955cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira            mBccListener = new RecipientTextWatcher(mBcc, this);
956cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        }
957cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        mBcc.addTextChangedListener(mBccListener);
95875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        mFromSpinner.setOnAccountChangedListener(this);
959818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        mAttachmentsView.setAttachmentChangesListener(this);
96075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    }
96175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
962326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    private void initActionBar(int action) {
963326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        mComposeMode = action;
964eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        ActionBar actionBar = getActionBar();
965e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        if (actionBar == null) {
966e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira            return;
967e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        }
968326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        if (action == ComposeActivity.COMPOSE) {
969eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
970eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            actionBar.setTitle(R.string.compose);
971326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        } else {
972eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            actionBar.setTitle(null);
973326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            if (mComposeModeAdapter == null) {
974326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                mComposeModeAdapter = new ComposeModeAdapter(this);
975326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            }
976eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
977eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            actionBar.setListNavigationCallbacks(mComposeModeAdapter, this);
978326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            switch (action) {
979326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                case ComposeActivity.REPLY:
980eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira                    actionBar.setSelectedNavigationItem(0);
981326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                    break;
982326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                case ComposeActivity.REPLY_ALL:
983eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira                    actionBar.setSelectedNavigationItem(1);
984326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                    break;
985326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                case ComposeActivity.FORWARD:
986eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira                    actionBar.setSelectedNavigationItem(2);
987326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                    break;
988326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            }
9896349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        }
990fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira        actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME,
991fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira                ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME);
992fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira        actionBar.setHomeButtonEnabled(true);
9936349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira    }
9946349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira
99546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    private void initFromRefMessage(int action, String recipientAddress) {
99696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        setFieldsFromRefMessage(action, recipientAddress);
99796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        if (mRefMessage != null) {
99896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            // CC field only gets populated when doing REPLY_ALL.
99996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            // BCC never gets auto-populated, unless the user is editing
100096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            // a draft with one.
100129a717e1047a2b50574e358c94a8ee8a41f377e9Mindy Pereira            if (!TextUtils.isEmpty(mCc.getText()) && action == REPLY_ALL) {
100296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira                mCcBccView.show(false, true, false);
100396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            }
100496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        }
100596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        updateHideOrShowCcBcc();
100696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    }
100796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira
100896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    private void setFieldsFromRefMessage(int action, String recipientAddress) {
10098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        setSubject(mRefMessage, action);
10108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // Setup recipients
10118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (action == FORWARD) {
10128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            mForward = true;
10138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
10148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        initRecipientsFromRefMessage(recipientAddress, mRefMessage, action);
1015e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        initQuotedTextFromRefMessage(mRefMessage, action);
10168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (action == ComposeActivity.FORWARD || mAttachmentsChanged) {
10178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            initAttachments(mRefMessage);
10186349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira        }
1019c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira    }
1020c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira
1021e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private void initFromDraftMessage(Message message) {
1022bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        LogUtils.d(LOG_TAG, "Intializing draft from previous draft message");
1023bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
1024bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        mDraft = message;
1025bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        mDraftId = message.id;
1026bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        mSubject.setText(message.subject);
1027bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        mForward = message.draftType == UIProvider.DraftType.FORWARD;
1028bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        final List<String> toAddresses = Arrays.asList(message.getToAddresses());
1029bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        addToAddresses(toAddresses);
1030bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        addCcAddresses(Arrays.asList(message.getCcAddresses()), toAddresses);
1031bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        addBccAddresses(Arrays.asList(message.getBccAddresses()));
10322421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira        if (message.hasAttachments) {
10332421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira            List<Attachment> attachments = message.getAttachments();
10342421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira            for (Attachment a : attachments) {
10355c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang                addAttachmentAndUpdateView(a);
10362421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira            }
10372421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira        }
1038cc8e7db940b2ad6c673e84ca7addae9295c10a33Mindy Pereira        int quotedTextIndex = message.appendRefMessageContent ?
1039002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                message.quotedTextOffset : -1;
1040bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        // Set the body
1041002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        CharSequence quotedText = null;
1042bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (!TextUtils.isEmpty(message.bodyHtml)) {
1043752222d839d9afeb5c4665669eab81645e413495Mindy Pereira            CharSequence htmlText = "";
1044002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            if (quotedTextIndex > -1) {
1045752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                // Find the offset in the htmltext of the actual quoted text and strip it out.
1046752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                quotedTextIndex = QuotedTextView.findQuotedTextIndex(message.bodyHtml);
1047752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                if (quotedTextIndex > -1) {
1048752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                    htmlText = Html.fromHtml(message.bodyHtml.substring(0, quotedTextIndex));
1049752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                    quotedText = message.bodyHtml.subSequence(quotedTextIndex,
1050752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                            message.bodyHtml.length());
1051752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                }
10521a6e938c8a97092e332707a55edb5a53996edf98Mindy Pereira            } else {
10531a6e938c8a97092e332707a55edb5a53996edf98Mindy Pereira                htmlText = Html.fromHtml(message.bodyHtml);
1054002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            }
1055002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            mBodyView.setText(htmlText);
1056bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        } else {
1057752222d839d9afeb5c4665669eab81645e413495Mindy Pereira            final String body = message.bodyText;
1058752222d839d9afeb5c4665669eab81645e413495Mindy Pereira            final CharSequence bodyText = !TextUtils.isEmpty(body) ?
1059752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                    (quotedTextIndex > -1 ?
1060752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                            message.bodyText.substring(0, quotedTextIndex) : message.bodyText)
1061752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                            : "";
1062002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            if (quotedTextIndex > -1) {
1063752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                quotedText = !TextUtils.isEmpty(body) ? message.bodyText.substring(quotedTextIndex)
1064752222d839d9afeb5c4665669eab81645e413495Mindy Pereira                        : null;
1065002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            }
1066002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            mBodyView.setText(bodyText);
1067002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        }
1068002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        if (quotedTextIndex > -1 && quotedText != null) {
10693971323f24b15b541f7460c1a4db42d78eb1873bMindy Pereira            mQuotedTextView.setQuotedTextFromDraft(quotedText, mForward);
1070bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
1071bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    }
1072bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
10738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    /**
10748eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * Fill all the widgets with the content found in the Intent Extra, if any.
10758eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * Also apply the same style to all widgets. Note: if initFromExtras is
10768eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * called as a result of switching between reply, reply all, and forward per
10778eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * the latest revision of Gmail, and the user has already made changes to
10788eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * attachments on a previous incarnation of the message (as a reply, reply
10798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * all, or forward), the original attachments from the message will not be
10808eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * re-instantiated. The user's changes will be respected. This follows the
10818eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * web gmail interaction.
10828eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     */
10838eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    public void initFromExtras(Intent intent) {
10848eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // If we were invoked with a SENDTO intent, the value
10858eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // should take precedence
10868eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        final Uri dataUri = intent.getData();
10878eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (dataUri != null) {
10888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            if (MAIL_TO.equals(dataUri.getScheme())) {
10898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                initFromMailTo(dataUri.toString());
10908eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            } else {
10910b4f28ed53a7f1617dadf3b34de8c743a1733ce5Mindy Pereira                if (!mAccount.composeIntentUri.equals(dataUri)) {
10928eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    String toText = dataUri.getSchemeSpecificPart();
10938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    if (toText != null) {
10948eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                        mTo.setText("");
1095dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira                        addToAddresses(Arrays.asList(TextUtils.split(toText, ",")));
10968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    }
10978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                }
10988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
10998eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11008eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        String[] extraStrings = intent.getStringArrayExtra(Intent.EXTRA_EMAIL);
11028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (extraStrings != null) {
11038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            addToAddresses(Arrays.asList(extraStrings));
11048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        extraStrings = intent.getStringArrayExtra(Intent.EXTRA_CC);
11068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (extraStrings != null) {
11078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            addCcAddresses(Arrays.asList(extraStrings), null);
11088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        extraStrings = intent.getStringArrayExtra(Intent.EXTRA_BCC);
11108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (extraStrings != null) {
11118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            addBccAddresses(Arrays.asList(extraStrings));
11128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        String extraString = intent.getStringExtra(Intent.EXTRA_SUBJECT);
11158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (extraString != null) {
11168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            mSubject.setText(extraString);
11178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        for (String extra : ALL_EXTRAS) {
11208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            if (intent.hasExtra(extra)) {
11218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                String value = intent.getStringExtra(extra);
11228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                if (EXTRA_TO.equals(extra)) {
1123dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira                    addToAddresses(Arrays.asList(TextUtils.split(value, ",")));
11248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                } else if (EXTRA_CC.equals(extra)) {
1125dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira                    addCcAddresses(Arrays.asList(TextUtils.split(value, ",")), null);
11268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                } else if (EXTRA_BCC.equals(extra)) {
1127dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira                    addBccAddresses(Arrays.asList(TextUtils.split(value, ",")));
11288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                } else if (EXTRA_SUBJECT.equals(extra)) {
11298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    mSubject.setText(value);
11308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                } else if (EXTRA_BODY.equals(extra)) {
11318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    setBody(value, true /* with signature */);
11328eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                }
11338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
11348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        Bundle extras = intent.getExtras();
11378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (extras != null) {
11388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            CharSequence text = extras.getCharSequence(Intent.EXTRA_TEXT);
11398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            if (text != null) {
11408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                setBody(text, true /* with signature */);
11418eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
11428eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
1143e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    }
1144e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira
11458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    @VisibleForTesting
11468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    protected String decodeEmailInUri(String s) throws UnsupportedEncodingException {
1147a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira        // TODO: handle the case where there are spaces in the display name as
1148a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira        // well as the email such as "Guy with spaces <guy+with+spaces@gmail.com>"
1149a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira        // as they could be encoded ambiguously.
11508eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // Since URLDecode.decode changes + into ' ', and + is a valid
11518eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // email character, we need to find/ replace these ourselves before
11528eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // decoding.
11538eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        String replacePlus = s.replace("+", "%2B");
1154a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira        try {
1155a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            return URLDecoder.decode(replacePlus, UTF8_ENCODING_NAME);
1156a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira        } catch (IllegalArgumentException e) {
1157a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) {
1158a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira                LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), s);
1159a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            } else {
1160a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira                LogUtils.e(LOG_TAG, e, "Exception  while decoding mailto address");
1161a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            }
1162a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            return null;
1163a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira        }
11648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    }
11658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11668eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    /**
11678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * Initialize the compose view from a String representing a mailTo uri.
11688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     * @param mailToString The uri as a string.
11698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira     */
11708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    public void initFromMailTo(String mailToString) {
11718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // We need to disguise this string as a URI in order to parse it
11728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        // TODO:  Remove this hack when http://b/issue?id=1445295 gets fixed
11738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        Uri uri = Uri.parse("foo://" + mailToString);
11748eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        int index = mailToString.indexOf("?");
11758eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        int length = "mailto".length() + 1;
11768eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        String to;
11778eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        try {
11788eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            // Extract the recipient after mailto:
11798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            if (index == -1) {
11808eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                to = decodeEmailInUri(mailToString.substring(length));
11818eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            } else {
11828eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                to = decodeEmailInUri(mailToString.substring(length, index));
11838eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
1184a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            if (!TextUtils.isEmpty(to)) {
1185a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira                addToAddresses(Arrays.asList(TextUtils.split(to, ",")));
1186a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira            }
11878eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        } catch (UnsupportedEncodingException e) {
11888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) {
11898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), mailToString);
11908eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            } else {
11918eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                LogUtils.e(LOG_TAG, e, "Exception  while decoding mailto address");
11928eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
11938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
11948eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        List<String> cc = uri.getQueryParameters("cc");
11968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        addCcAddresses(Arrays.asList(cc.toArray(new String[cc.size()])), null);
11978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
11988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        List<String> otherTo = uri.getQueryParameters("to");
11998eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        addToAddresses(Arrays.asList(otherTo.toArray(new String[otherTo.size()])));
12008eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
12018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        List<String> bcc = uri.getQueryParameters("bcc");
12028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        addBccAddresses(Arrays.asList(bcc.toArray(new String[bcc.size()])));
12038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
12048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        List<String> subject = uri.getQueryParameters("subject");
12058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (subject.size() > 0) {
12068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            try {
12078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                mSubject.setText(URLDecoder.decode(subject.get(0), UTF8_ENCODING_NAME));
12088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            } catch (UnsupportedEncodingException e) {
12098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                LogUtils.e(LOG_TAG, "%s while decoding subject '%s'",
12108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                        e.getMessage(), subject);
12118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
12128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
12138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
12148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        List<String> body = uri.getQueryParameters("body");
12158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (body.size() > 0) {
12168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            try {
12178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                setBody(URLDecoder.decode(body.get(0), UTF8_ENCODING_NAME),
12188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                        true /* with signature */);
12198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            } catch (UnsupportedEncodingException e) {
12208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                LogUtils.e(LOG_TAG, "%s while decoding body '%s'", e.getMessage(), body);
12218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
12228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        }
12238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira    }
12248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira
1225bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira    @VisibleForTesting
1226bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira    protected void initAttachments(Message refMessage) {
1227434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        addAttachments(refMessage.getAttachments());
1228434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei    }
1229434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei
1230434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei    public long addAttachments(List<Attachment> attachments) {
1231434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        long size = 0;
1232434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        AttachmentFailureException error = null;
1233434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        for (Attachment a : attachments) {
1234434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            try {
1235434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                size += mAttachmentsView.addAttachment(mAccount, a);
1236434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            } catch (AttachmentFailureException e) {
1237434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                error = e;
1238434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            }
1239434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        }
1240434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        if (error != null) {
1241434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            LogUtils.e(LOG_TAG, error, "Error adding attachment");
1242434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            if (attachments.size() > 1) {
1243434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                showAttachmentTooBigToast(R.string.too_large_to_attach_multiple);
1244434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            } else {
1245434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                showAttachmentTooBigToast(error.getErrorRes());
1246434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            }
12473cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira        }
1248434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        return size;
12493cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira    }
12503cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira
12513cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira    /**
12523cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira     * When an attachment is too large to be added to a message, show a toast.
12533cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira     * This method also updates the position of the toast so that it is shown
12543cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira     * clearly above they keyboard if it happens to be open.
12553cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira     */
1256434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei    private void showAttachmentTooBigToast(int errorRes) {
1257434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        String maxSize = AttachmentUtils.convertToHumanReadableSize(
1258434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                getApplicationContext(), mAccount.settings.getMaxAttachmentSize());
1259434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        showErrorToast(getString(errorRes, maxSize));
12603cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira    }
12613cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira
1262434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei    private void showErrorToast(String message) {
1263434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        Toast t = Toast.makeText(this, message, Toast.LENGTH_LONG);
1264434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei        t.setText(message);
12653cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira        t.setGravity(Gravity.CENTER_HORIZONTAL, 0,
12663cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira                getResources().getDimensionPixelSize(R.dimen.attachment_toast_yoffset));
12673cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira        t.show();
1268eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
1269eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
1270f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook    private void initAttachmentsFromIntent(Intent intent) {
127103ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook        Bundle extras = intent.getExtras();
127203ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook        if (extras == null) {
127303ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook            extras = Bundle.EMPTY;
127403ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook        }
1275f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook        final String action = intent.getAction();
1276f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook        if (!mAttachmentsChanged) {
1277f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            long totalSize = 0;
1278f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            if (extras.containsKey(EXTRA_ATTACHMENTS)) {
1279f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                String[] uris = (String[]) extras.getSerializable(EXTRA_ATTACHMENTS);
1280f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                for (String uriString : uris) {
1281f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    final Uri uri = Uri.parse(uriString);
1282f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    long size = 0;
1283f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    try {
12845c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang                        size =  mAttachmentsView.addAttachment(mAccount, uri);
1285f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    } catch (AttachmentFailureException e) {
1286f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                        LogUtils.e(LOG_TAG, e, "Error adding attachment");
1287434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                        showAttachmentTooBigToast(e.getErrorRes());
1288f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    }
1289f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    totalSize += size;
1290f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                }
1291f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            }
1292f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            if (Intent.ACTION_SEND.equals(action) && extras.containsKey(Intent.EXTRA_STREAM)) {
1293f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
1294f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                long size = 0;
1295f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                try {
12965c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang                    size =  mAttachmentsView.addAttachment(mAccount, uri);
1297f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                } catch (AttachmentFailureException e) {
1298f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    LogUtils.e(LOG_TAG, e, "Error adding attachment");
1299434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                    showAttachmentTooBigToast(e.getErrorRes());
1300f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                }
1301f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                totalSize += size;
1302f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            }
1303f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook
1304f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            if (Intent.ACTION_SEND_MULTIPLE.equals(action)
1305f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    && extras.containsKey(Intent.EXTRA_STREAM)) {
1306f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                ArrayList<Parcelable> uris = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
1307434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                ArrayList<Attachment> attachments = new ArrayList<Attachment>();
1308f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                for (Parcelable uri : uris) {
1309f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    try {
1310434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                        attachments.add(mAttachmentsView.generateLocalAttachment((Uri) uri));
1311f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    } catch (AttachmentFailureException e) {
1312f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                        LogUtils.e(LOG_TAG, e, "Error adding attachment");
1313434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                        String maxSize = AttachmentUtils.convertToHumanReadableSize(
1314434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                                getApplicationContext(),
1315434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                                mAccount.settings.getMaxAttachmentSize());
1316434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                        showErrorToast(getString(R.string.generic_attachment_problem, maxSize));
1317f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                    }
1318f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                }
1319434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                totalSize += addAttachments(attachments);
1320f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            }
1321f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook
1322f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            if (totalSize > 0) {
1323f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                mAttachmentsChanged = true;
1324f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook                updateSaveUi();
1325f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook            }
1326f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook        }
1327f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook    }
1328f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook
1329f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook
1330e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    private void initQuotedTextFromRefMessage(Message refMessage, int action) {
1331e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        if (mRefMessage != null && (action == REPLY || action == REPLY_ALL || action == FORWARD)) {
13329932dee248718d2cec993d93b5115973d1389d0aMindy Pereira            mQuotedTextView.setQuotedText(action, refMessage, action != FORWARD);
13339932dee248718d2cec993d93b5115973d1389d0aMindy Pereira        }
133446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
133546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
133646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    private void updateHideOrShowCcBcc() {
1337ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        // Its possible there is a menu item OR a button.
1338326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        boolean ccVisible = mCcBccView.isCcVisible();
1339326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        boolean bccVisible = mCcBccView.isBccVisible();
1340ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        if (mCcBccButton != null) {
1341326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira            if (!ccVisible || !bccVisible) {
1342ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                mCcBccButton.setVisibility(View.VISIBLE);
1343326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira                mCcBccButton.setText(getString(!ccVisible ? R.string.add_cc_label
1344ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                        : R.string.add_bcc_label));
1345ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            } else {
1346cd0b0b950efebfc3964334067747b97e61c4f027mindyp                mCcBccButton.setVisibility(View.INVISIBLE);
1347ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            }
1348ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        }
134946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
135046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
1351a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira    private void showCcBcc(Bundle state) {
1352326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        if (state != null && state.containsKey(EXTRA_SHOW_CC)) {
1353326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira            boolean showCc = state.getBoolean(EXTRA_SHOW_CC);
1354326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira            boolean showBcc = state.getBoolean(EXTRA_SHOW_BCC);
1355326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira            if (showCc || showBcc) {
1356326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira                mCcBccView.show(false, showCc, showBcc);
1357326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira            }
1358326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira        }
1359326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira    }
1360326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira
1361013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    /**
1362013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira     * Add attachment and update the compose area appropriately.
1363013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira     * @param data
1364013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira     */
1365013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    public void addAttachmentAndUpdateView(Intent data) {
13662421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira        addAttachmentAndUpdateView(data != null ? data.getData() : (Uri) null);
13672421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira    }
13682421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira
13695c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    public void addAttachmentAndUpdateView(Uri contentUri) {
13705c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        if (contentUri == null) {
13712421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira            return;
13722421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira        }
1373013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira        try {
13745c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang            addAttachmentAndUpdateView(mAttachmentsView.generateLocalAttachment(contentUri));
13755c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        } catch (AttachmentFailureException e) {
13765c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang            LogUtils.e(LOG_TAG, e, "Error adding attachment");
1377434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            showErrorToast(getResources().getString(
1378434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                    e.getErrorRes(),
1379434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                    AttachmentUtils.convertToHumanReadableSize(
1380434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei                            getApplicationContext(), mAccount.settings.getMaxAttachmentSize())));
13815c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        }
13825c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    }
13835c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang
13845c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang    public void addAttachmentAndUpdateView(Attachment attachment) {
13855c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang        try {
1386434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            long size = mAttachmentsView.addAttachment(mAccount, attachment);
13879932dee248718d2cec993d93b5115973d1389d0aMindy Pereira            if (size > 0) {
13889932dee248718d2cec993d93b5115973d1389d0aMindy Pereira                mAttachmentsChanged = true;
13899932dee248718d2cec993d93b5115973d1389d0aMindy Pereira                updateSaveUi();
1390013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira            }
13919932dee248718d2cec993d93b5115973d1389d0aMindy Pereira        } catch (AttachmentFailureException e) {
13929932dee248718d2cec993d93b5115973d1389d0aMindy Pereira            LogUtils.e(LOG_TAG, e, "Error adding attachment");
1393434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei            showAttachmentTooBigToast(e.getErrorRes());
1394013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira        }
1395013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    }
1396013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira
13973ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    void initRecipientsFromRefMessage(String recipientAddress, Message refMessage,
139846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            int action) {
13994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // Don't populate the address if this is a forward.
14004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        if (action == ComposeActivity.FORWARD) {
14014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            return;
14024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
140333fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira        initReplyRecipients(mAccount.name, refMessage, action);
14044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
14054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
1406818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira    @VisibleForTesting
14073ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    void initReplyRecipients(String account, Message refMessage, int action) {
14084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // This is the email address of the current user, i.e. the one composing
14094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // the reply.
14104a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira        final String accountEmail = Address.getEmailAddress(account).getAddress();
14111469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira        String fromAddress = getAddress(refMessage.from);
14125ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        String[] sentToAddresses = refMessage.getToAddresses();
14133ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        String replytoAddress = refMessage.replyTo;
1414a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        final Collection<String> toAddresses;
14154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // If this is a reply, the Cc list is empty. If this is a reply-all, the
14174a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // Cc list is the union of the To and Cc recipients of the original
14184a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // message, excluding the current user's email address and any addresses
1419a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        // already on the To list.
1420a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        if (action == ComposeActivity.REPLY) {
14213ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            toAddresses = initToRecipients(account, accountEmail, fromAddress, replytoAddress,
14221469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira                    sentToAddresses);
1423a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira            addToAddresses(toAddresses);
1424a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        } else if (action == ComposeActivity.REPLY_ALL) {
14254a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            final Set<String> ccAddresses = Sets.newHashSet();
14263ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            toAddresses = initToRecipients(account, accountEmail, fromAddress, replytoAddress,
14279b18a9a10538418f0280380e81452c52f5ce2542Mindy Pereira                    sentToAddresses);
1428154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira            addToAddresses(toAddresses);
14294a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            addRecipients(accountEmail, ccAddresses, sentToAddresses);
14305ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp            addRecipients(accountEmail, ccAddresses, refMessage.getCcAddresses());
14314a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            addCcAddresses(ccAddresses, toAddresses);
14324a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
14334a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
14344a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14351469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira    private String getAddress(String toParse) {
14361469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira        if (!TextUtils.isEmpty(toParse)) {
14371469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira            Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(toParse);
14381469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira            if (tokens.length > 0) {
14391469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira                return tokens[0].getAddress();
14401469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira            }
14411469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira        }
14421469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira        return "";
14431469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira    }
14441469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira
14454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    private void addToAddresses(Collection<String> addresses) {
14464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        addAddressesToList(addresses, mTo);
14474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
14484a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14494a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    private void addCcAddresses(Collection<String> addresses, Collection<String> toAddresses) {
14508eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        addCcAddressesToList(tokenizeAddressList(addresses),
14518eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                toAddresses != null ? tokenizeAddressList(toAddresses) : null, mCc);
14524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
14534a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
1454bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    private void addBccAddresses(Collection<String> addresses) {
1455bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        addAddressesToList(addresses, mBcc);
1456bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    }
1457bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
14584a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    @VisibleForTesting
14594a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    protected void addCcAddressesToList(List<Rfc822Token[]> addresses,
14604a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            List<Rfc822Token[]> compareToList, RecipientEditTextView list) {
14614a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        String address;
14624a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        if (compareToList == null) {
14648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            for (Rfc822Token[] tokens : addresses) {
14658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                for (int i = 0; i < tokens.length; i++) {
14668eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    address = tokens[i].toString();
14674a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira                    list.append(address + END_TOKEN);
14684a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira                }
14694a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            }
14708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira        } else {
14718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            HashSet<String> compareTo = convertToHashSet(compareToList);
14728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            for (Rfc822Token[] tokens : addresses) {
14738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                for (int i = 0; i < tokens.length; i++) {
14748eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    address = tokens[i].toString();
14758eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    // Check if this is a duplicate:
14768eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    if (!compareTo.contains(tokens[i].getAddress())) {
14778eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                        // Get the address here
14788eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                        list.append(address + END_TOKEN);
14798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                    }
14808eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira                }
14818eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
14824a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
14834a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
14844a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14854a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    private HashSet<String> convertToHashSet(List<Rfc822Token[]> list) {
14864a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        HashSet<String> hash = new HashSet<String>();
14874a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        for (Rfc822Token[] tokens : list) {
14884a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            for (int i = 0; i < tokens.length; i++) {
14894a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira                hash.add(tokens[i].getAddress());
14904a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            }
14914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
14924a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        return hash;
14934a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
14944a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    protected List<Rfc822Token[]> tokenizeAddressList(Collection<String> addresses) {
14964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        @VisibleForTesting
14974a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        List<Rfc822Token[]> tokenized = new ArrayList<Rfc822Token[]>();
14984a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
14994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        for (String address: addresses) {
15004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            tokenized.add(Rfc822Tokenizer.tokenize(address));
15014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
15024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        return tokenized;
15034a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
15044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
15054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    @VisibleForTesting
15064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    void addAddressesToList(Collection<String> addresses, RecipientEditTextView list) {
15074a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        for (String address : addresses) {
15084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            addAddressToList(address, list);
15094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
15104a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
15114a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
15124a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    private void addAddressToList(String address, RecipientEditTextView list) {
15134a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        if (address == null || list == null)
15144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            return;
15154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
15164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address);
15174a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
15184a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        for (int i = 0; i < tokens.length; i++) {
15194a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            list.append(tokens[i] + END_TOKEN);
15204a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
15214a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
15224a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
15234a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    @VisibleForTesting
15244a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    protected Collection<String> initToRecipients(String account, String accountEmail,
15253ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            String senderAddress, String replyToAddress, String[] inToAddresses) {
15264a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // The To recipient is the reply-to address specified in the original
15274a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // message, unless it is:
15284a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // the current user OR a custom from of the current user, in which case
15294a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // it's the To recipient list of the original message.
15304a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        // OR missing, in which case use the sender of the original message
15314a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        Set<String> toAddresses = Sets.newHashSet();
15323ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        if (!TextUtils.isEmpty(replyToAddress)) {
15333ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            toAddresses.add(replyToAddress);
15344a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        } else {
1535cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira            if (!recipientMatchesThisAccount(account, senderAddress)) {
15361469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira                toAddresses.add(senderAddress);
15371469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira            } else {
15381469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira                // This happens if the user replies to a message they originally
15391883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira                // wrote. In this case, "reply" really means "re-send," so we
15401883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira                // target the original recipients. This works as expected even
15411883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira                // if the user sent the original message to themselves.
15421469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira                toAddresses.addAll(Arrays.asList(inToAddresses));
15431469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira            }
15444a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
15454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        return toAddresses;
15464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira    }
15474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira
1548cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira    private void addRecipients(String accountAddress, Set<String> recipients, String[] addresses) {
15494a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        for (String email : addresses) {
1550cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira            // Do not add this account, or any of its custom from addresses, to
1551cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira            // the list of recipients.
15524a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira            final String recipientAddress = Address.getEmailAddress(email).getAddress();
1553cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira            if (!recipientMatchesThisAccount(accountAddress, recipientAddress)) {
15544a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira                recipients.add(email.replace("\"\"", ""));
15554a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira            }
15564a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira        }
155746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
155846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
1559cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira    /**
1560cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     * A recipient matches this account if it has the same address as the
1561cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     * currently selected account OR one of the custom from addresses associated
1562cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     * with the currently selected account.
1563cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     * @param accountAddress currently selected account
1564cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     * @param recipientAddress address we are comparing with the currently selected account
1565cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     * @return
1566cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira     */
1567cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira    protected boolean recipientMatchesThisAccount(String accountAddress, String recipientAddress) {
1568cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira        return accountAddress.equalsIgnoreCase(recipientAddress)
1569cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira                || ReplyFromAccount.isCustomFrom(recipientAddress,
1570cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira                        mFromSpinner.getReplyFromAccounts());
1571cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira    }
1572cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira
15733ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    private void setSubject(Message refMessage, int action) {
15743ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        String subject = refMessage.subject;
157546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        String prefix;
157646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        String correctedSubject = null;
157746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        if (action == ComposeActivity.COMPOSE) {
157846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            prefix = "";
157946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        } else if (action == ComposeActivity.FORWARD) {
158046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            prefix = getString(R.string.forward_subject_label);
158146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        } else {
158246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            prefix = getString(R.string.reply_subject_label);
158346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        }
158446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
158546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        // Don't duplicate the prefix
1586c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira        if (!TextUtils.isEmpty(subject)
1587c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira                && subject.toLowerCase().startsWith(prefix.toLowerCase())) {
158846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            correctedSubject = subject;
158946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        } else {
159046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            correctedSubject = String
159146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira                    .format(getString(R.string.formatted_subject), prefix, subject);
159246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        }
159346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        mSubject.setText(correctedSubject);
159446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
159546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
1596818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira    private void initRecipients() {
1597818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        setupRecipients(mTo);
1598818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        setupRecipients(mCc);
1599818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        setupRecipients(mBcc);
1600eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
1601eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
1602818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira    private void setupRecipients(RecipientEditTextView view) {
1603679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook        view.setAdapter(new RecipientAdapter(this, mAccount));
1604c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira        view.setTokenizer(new Rfc822Tokenizer());
160582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (mValidator == null) {
1606679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook            final String accountName = mAccount.name;
160733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira            int offset = accountName.indexOf("@") + 1;
160833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira            String account = accountName;
1609c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira            if (offset > -1) {
161033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira                account = account.substring(accountName.indexOf("@") + 1);
1611c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira            }
161282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mValidator = new Rfc822Validator(account);
1613c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira        }
161482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        view.setValidator(mValidator);
16158e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    }
16168e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira
16178e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    @Override
16188e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    public void onClick(View v) {
16198e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        int id = v.getId();
16208e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        switch (id) {
1621a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira            case R.id.add_cc_bcc:
16228e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira                // Verify that cc/ bcc aren't showing.
16238e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira                // Animate in cc/bcc.
1624a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira                showCcBccViews();
16258e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira                break;
1626cd0b0b950efebfc3964334067747b97e61c4f027mindyp            case R.id.add_photo_attachment:
1627cd0b0b950efebfc3964334067747b97e61c4f027mindyp                doAttach(MIME_TYPE_PHOTO);
1628cd0b0b950efebfc3964334067747b97e61c4f027mindyp                break;
1629cd0b0b950efebfc3964334067747b97e61c4f027mindyp            case R.id.add_video_attachment:
1630cd0b0b950efebfc3964334067747b97e61c4f027mindyp                doAttach(MIME_TYPE_VIDEO);
1631cd0b0b950efebfc3964334067747b97e61c4f027mindyp                break;
16328e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira        }
16338e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira    }
1634b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira
1635b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira    @Override
1636b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira    public boolean onCreateOptionsMenu(Menu menu) {
1637b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        super.onCreateOptionsMenu(menu);
1638b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        // Don't render any menu items when there are no accounts.
1639b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (mAccounts == null || mAccounts.length == 0) {
1640b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            return true;
1641b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        }
1642b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        MenuInflater inflater = getMenuInflater();
1643b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        inflater.inflate(R.menu.compose_menu, menu);
164482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        mSave = menu.findItem(R.id.save);
164582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        mSend = menu.findItem(R.id.send);
16463ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira        MenuItem helpItem = menu.findItem(R.id.help_info_menu_item);
16473ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira        MenuItem sendFeedbackItem = menu.findItem(R.id.feedback_menu_item);
16483ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira        if (helpItem != null) {
16493ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira            helpItem.setVisible(mAccount != null
16503ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira                    && mAccount.supportsCapability(AccountCapabilities.HELP_CONTENT));
16513ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira        }
16523ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira        if (sendFeedbackItem != null) {
16533ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira            sendFeedbackItem.setVisible(mAccount != null
16543ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira                    && mAccount.supportsCapability(AccountCapabilities.SEND_FEEDBACK));
16553ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira        }
1656b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        return true;
1657b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira    }
1658b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira
1659b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira    @Override
1660ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira    public boolean onPrepareOptionsMenu(Menu menu) {
1661ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        MenuItem ccBcc = menu.findItem(R.id.add_cc_bcc);
1662818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira        if (ccBcc != null && mCc != null) {
1663ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            // Its possible there is a menu item OR a button.
1664ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            boolean ccFieldVisible = mCc.isShown();
1665ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            boolean bccFieldVisible = mBcc.isShown();
1666ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            if (!ccFieldVisible || !bccFieldVisible) {
1667ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                ccBcc.setVisible(true);
1668ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                ccBcc.setTitle(getString(!ccFieldVisible ? R.string.add_cc_label
1669ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                        : R.string.add_bcc_label));
1670ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            } else {
1671ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                ccBcc.setVisible(false);
1672ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            }
1673ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        }
167475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        if (mSave != null) {
167575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            mSave.setEnabled(shouldSave());
167675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
1677ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        return true;
1678ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira    }
1679ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira
1680ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira    @Override
1681b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira    public boolean onOptionsItemSelected(MenuItem item) {
1682b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        int id = item.getItemId();
168375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        boolean handled = true;
1684b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        switch (id) {
16852db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira            case R.id.add_photo_attachment:
16862db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira                doAttach(MIME_TYPE_PHOTO);
16872db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira                break;
16882db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira            case R.id.add_video_attachment:
16892db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira                doAttach(MIME_TYPE_VIDEO);
16907b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira                break;
1691ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira            case R.id.add_cc_bcc:
1692ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira                showCcBccViews();
1693b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira                break;
169433fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira            case R.id.save:
169548e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira                doSave(true);
169633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira                break;
169733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira            case R.id.send:
169833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira                doSend();
169975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                break;
1700efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira            case R.id.discard:
1701efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira                doDiscard();
1702efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira                break;
17031f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira            case R.id.settings:
17041f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira                Utils.showSettings(this, mAccount);
17051f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira                break;
1706fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira            case android.R.id.home:
1707daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook                onAppUpPressed();
1708fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira                break;
1709fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira            case R.id.help_info_menu_item:
171030745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook                Utils.showHelp(this, mAccount, getString(R.string.compose_help_context));
1711fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira                break;
1712fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira            case R.id.feedback_menu_item:
171317beb0b8aee78a39a2094a48ba7f55a602f701cbPaul Westbrook                Utils.sendFeedback(this, mAccount, false);
1714fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira                break;
171575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            default:
171675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                handled = false;
171733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira                break;
1718b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        }
1719b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira        return !handled ? super.onOptionsItemSelected(item) : handled;
1720b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira    }
1721326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
1722b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    @Override
1723b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    public void onBackPressed() {
1724b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        // If we are showing the wait fragment, just exit.
1725b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (getWaitFragment() != null) {
1726b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            finish();
1727b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        } else {
1728b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            super.onBackPressed();
1729b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        }
1730b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    }
1731b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira
1732daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook    private void onAppUpPressed() {
1733daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        if (mLaunchedFromEmail) {
1734daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            // If this was started from Gmail, simply treat app up as the system back button, so
1735daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            // that the last view is restored.
1736daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            onBackPressed();
1737daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook            return;
1738daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        }
1739daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook
1740daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        // Fire the main activity to ensure it launches the "top" screen of mail.
1741daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        // Since the main Activity is singleTask, it should revive that task if it was already
1742daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        // started.
17435ad02918f663bc52522a2505de985df9ef5ea347Mindy Pereira        Folder defaultInbox = new Folder();
17445ad02918f663bc52522a2505de985df9ef5ea347Mindy Pereira        defaultInbox.uri = mAccount.settings.defaultInbox;
1745daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        final Intent mailIntent =
174696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira                Utils.createViewFolderIntent(defaultInbox, mAccount);
1747daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook
1748daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        mailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |
1749daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook                Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1750daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        startActivity(mailIntent);
1751daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook        finish();
1752daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook    }
1753daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook
175433fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira    private void doSend() {
17558aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira        clearImeText();
175682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        sendOrSaveWithSanityChecks(false, true, false);
175733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira    }
175833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira
175948e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira    private void doSave(boolean showToast) {
176048e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira        // Clear the IME composing suggestions from the body and subject before saving.
17618aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira        clearImeText();
1762eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        sendOrSaveWithSanityChecks(true, showToast, false);
176348e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira    }
176448e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira
17658aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira    private void clearImeText() {
17668aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira        mBodyView.clearComposingText();
17678aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira        BaseInputConnection.removeComposingSpans(mBodyView.getEditableText());
17688aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira        mSubject.clearComposingText();
17698aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira        BaseInputConnection.removeComposingSpans(mSubject.getEditableText());
177082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
177182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
1772e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    @VisibleForTesting
1773e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public interface SendOrSaveCallback {
177482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask);
17757ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira        public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, Message message);
17767ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira        public Message getMessage();
177782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        public void sendOrSaveFinished(SendOrSaveTask sendOrSaveTask, boolean success);
177882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
177982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
1780e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    @VisibleForTesting
1781e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public static class SendOrSaveTask implements Runnable {
178282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        private final Context mContext;
178382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        @VisibleForTesting
1784e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        public final SendOrSaveCallback mSendOrSaveCallback;
1785e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        @VisibleForTesting
1786e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        public final SendOrSaveMessage mSendOrSaveMessage;
178782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
178882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        public SendOrSaveTask(Context context, SendOrSaveMessage message,
178982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                SendOrSaveCallback callback) {
179082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mContext = context;
179182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSendOrSaveCallback = callback;
179282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSendOrSaveMessage = message;
179382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
179482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
179582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        @Override
179682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        public void run() {
17977ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            final SendOrSaveMessage sendOrSaveMessage = mSendOrSaveMessage;
179882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
179992551d057965689f1952faeb06763f0762bc717fMindy Pereira            final ReplyFromAccount selectedAccount = sendOrSaveMessage.mAccount;
18007ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            Message message = mSendOrSaveCallback.getMessage();
18017ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            long messageId = message != null ? message.id : UIProvider.INVALID_MESSAGE_ID;
180282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // If a previous draft has been saved, in an account that is different
180382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // than what the user wants to send from, remove the old draft, and treat this
180482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // as a new message
18057ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            if (!selectedAccount.equals(sendOrSaveMessage.mAccount)) {
180682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                if (messageId != UIProvider.INVALID_MESSAGE_ID) {
180782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                    ContentResolver resolver = mContext.getContentResolver();
180882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                    ContentValues values = new ContentValues();
180982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                    values.put(BaseColumns._ID, messageId);
181092551d057965689f1952faeb06763f0762bc717fMindy Pereira                    if (selectedAccount.account.expungeMessageUri != null) {
181192551d057965689f1952faeb06763f0762bc717fMindy Pereira                        resolver.update(selectedAccount.account.expungeMessageUri, values, null,
1812eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira                                null);
1813cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                    } else {
1814cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                        // TODO(mindyp) delete the conversation.
1815eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira                    }
181682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                    // reset messageId to 0, so a new message will be created
181782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                    messageId = UIProvider.INVALID_MESSAGE_ID;
181882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                }
181982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
182082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
182182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            final long messageIdToSave = messageId;
182282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            if (messageIdToSave != UIProvider.INVALID_MESSAGE_ID) {
18237ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                sendOrSaveMessage.mValues.put(BaseColumns._ID, messageIdToSave);
182482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                mContext.getContentResolver().update(
18257ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                        Uri.parse(sendOrSaveMessage.mSave ? message.saveUri : message.sendUri),
18267ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                        sendOrSaveMessage.mValues, null, null);
182782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            } else {
18287ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                ContentResolver resolver = mContext.getContentResolver();
182992551d057965689f1952faeb06763f0762bc717fMindy Pereira                Uri messageUri = resolver
183092551d057965689f1952faeb06763f0762bc717fMindy Pereira                        .insert(sendOrSaveMessage.mSave ? selectedAccount.account.saveDraftUri
183192551d057965689f1952faeb06763f0762bc717fMindy Pereira                                : selectedAccount.account.sendMessageUri,
183292551d057965689f1952faeb06763f0762bc717fMindy Pereira                                sendOrSaveMessage.mValues);
18337ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                if (sendOrSaveMessage.mSave && messageUri != null) {
18347ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    Cursor messageCursor = resolver.query(messageUri,
18357ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                            UIProvider.MESSAGE_PROJECTION, null, null, null);
1836ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                    if (messageCursor != null) {
1837ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                        try {
1838ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                            if (messageCursor.moveToFirst()) {
1839ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                                // Broadcast notification that a new message has
1840ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                                // been allocated
1841ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                                mSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage,
1842ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                                        new Message(messageCursor));
1843ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                            }
1844ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                        } finally {
1845ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                            messageCursor.close();
1846ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook                        }
18477ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    }
18487ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                }
184982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
185082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
18517ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            if (!sendOrSaveMessage.mSave) {
185282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                UIProvider.incrementRecipientsTimesContacted(mContext,
18537ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                        (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.TO));
185482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                UIProvider.incrementRecipientsTimesContacted(mContext,
18557ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                        (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.CC));
185682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                UIProvider.incrementRecipientsTimesContacted(mContext,
18577ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                        (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.BCC));
185882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
185982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSendOrSaveCallback.sendOrSaveFinished(SendOrSaveTask.this, true);
186082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
186182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
186282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
186382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // Array of the outstanding send or save tasks.  Access is synchronized
186482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    // with the object itself
186582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /* package for testing */
1866e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    @VisibleForTesting
1867e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public ArrayList<SendOrSaveTask> mActiveTasks = Lists.newArrayList();
186882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private int mRequestId;
1869bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    private String mSignature;
1870b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private Account[] mAccounts;
187182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
1872e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    @VisibleForTesting
1873e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public static class SendOrSaveMessage {
187492551d057965689f1952faeb06763f0762bc717fMindy Pereira        final ReplyFromAccount mAccount;
187582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        final ContentValues mValues;
18763ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        final String mRefMessageId;
1877e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        @VisibleForTesting
1878e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        public final boolean mSave;
187982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        final int mRequestId;
188082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
188192551d057965689f1952faeb06763f0762bc717fMindy Pereira        public SendOrSaveMessage(ReplyFromAccount account, ContentValues values,
18823ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira                String refMessageId, boolean save) {
188382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mAccount = account;
188482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mValues = values;
188582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mRefMessageId = refMessageId;
188682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSave = save;
188782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mRequestId = mValues.hashCode() ^ hashCode();
188882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
188982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
189082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        int requestId() {
189182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            return mRequestId;
189282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
189382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
189482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
189582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
189682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Get the to recipients.
189782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
189882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public String[] getToAddresses() {
189982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        return getAddressesFromList(mTo);
190082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
190182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
190282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
190382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Get the cc recipients.
190482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
190582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public String[] getCcAddresses() {
190682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        return getAddressesFromList(mCc);
190782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
190882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
190982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
191082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Get the bcc recipients.
191182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
191282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public String[] getBccAddresses() {
191382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        return getAddressesFromList(mBcc);
191482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
191582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
191682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public String[] getAddressesFromList(RecipientEditTextView list) {
191782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (list == null) {
191882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            return new String[0];
191982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
192082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(list.getText());
192182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        int count = tokens.length;
192282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        String[] result = new String[count];
192382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        for (int i = 0; i < count; i++) {
192482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            result[i] = tokens[i].toString();
192582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
192682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        return result;
192782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
192882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
192982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
193082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Check for invalid email addresses.
193182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * @param to String array of email addresses to check.
193282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * @param wrongEmailsOut Emails addresses that were invalid.
193382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
193482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public void checkInvalidEmails(String[] to, List<String> wrongEmailsOut) {
1935e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira        if (mValidator == null) {
1936e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira            return;
1937e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira        }
193882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        for (String email : to) {
193982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            if (!mValidator.isValid(email)) {
194082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                wrongEmailsOut.add(email);
194182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
194282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
194382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
194482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
194582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
194682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Show an error because the user has entered an invalid recipient.
194782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * @param message
194882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
194982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public void showRecipientErrorDialog(String message) {
195082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        // Only 1 invalid recipients error dialog should be allowed up at a
195182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        // time.
195282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (mRecipientErrorDialog != null) {
195382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mRecipientErrorDialog.dismiss();
195482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
195582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        mRecipientErrorDialog = new AlertDialog.Builder(this).setMessage(message).setTitle(
195682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                R.string.recipient_error_dialog_title)
195782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                .setIconAttribute(android.R.attr.alertDialogIcon)
195882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                .setPositiveButton(
195982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                        R.string.ok, new Dialog.OnClickListener() {
19600bbc858506c95005f2840fa5dff495a9216d2665Marc Blank                            @Override
196182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                            public void onClick(DialogInterface dialog, int which) {
196282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                // after the user dismisses the recipient error
196382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                // dialog we want to make sure to refocus the
196482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                // recipient to field so they can fix the issue
196582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                // easily
196682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                if (mTo != null) {
196782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                    mTo.requestFocus();
196882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                }
196982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                                mRecipientErrorDialog = null;
197082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                            }
197182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                        }).show();
197282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
197382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
197482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
197582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Update the state of the UI based on whether or not the current draft
197682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * needs to be saved and the message is not empty.
197782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
1978eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    public void updateSaveUi() {
197982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (mSave != null) {
198082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSave.setEnabled((shouldSave() && !isBlank()));
198182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
198282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
198382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
198482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
198582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Returns true if we need to save the current draft.
198682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
198782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private boolean shouldSave() {
19887ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira        synchronized (mDraftLock) {
198982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // The message should only be saved if:
199082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // It hasn't been sent AND
199182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // Some text has been added to the message OR
199282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // an attachment has been added or removed
1993a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira            // AND there is actually something in the draft to save.
1994d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang            return (mTextChanged || mAttachmentsChanged || mReplyFromChanged)
1995a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira                    && !isBlank();
199682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
199782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
199882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
199982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
2000bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira     * Check if all fields are blank.
200182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * @return boolean
200282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
200382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public boolean isBlank() {
200482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        return mSubject.getText().length() == 0
2005bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                && (mBodyView.getText().length() == 0 || getSignatureStartPosition(mSignature,
2006bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                        mBodyView.getText().toString()) == 0)
2007bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                && mTo.length() == 0
2008bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                && mCc.length() == 0 && mBcc.length() == 0
2009bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                && mAttachmentsView.getAttachments().size() == 0;
2010bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    }
2011bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira
2012bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    @VisibleForTesting
2013bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    protected int getSignatureStartPosition(String signature, String bodyText) {
2014bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        int startPos = -1;
2015bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira
2016bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        if (TextUtils.isEmpty(signature) || TextUtils.isEmpty(bodyText)) {
2017bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira            return startPos;
2018bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        }
2019bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira
2020bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        int bodyLength = bodyText.length();
2021bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        int signatureLength = signature.length();
2022bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        String printableVersion = convertToPrintableSignature(signature);
2023bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        int printableLength = printableVersion.length();
2024bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira
2025bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        if (bodyLength >= printableLength
2026bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                && bodyText.substring(bodyLength - printableLength)
2027bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                .equals(printableVersion)) {
2028bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira            startPos = bodyLength - printableLength;
2029bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        } else if (bodyLength >= signatureLength
2030bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                && bodyText.substring(bodyLength - signatureLength)
2031bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira                .equals(signature)) {
2032bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira            startPos = bodyLength - signatureLength;
2033bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        }
2034bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        return startPos;
203582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
203682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
203782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
203882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Allows any changes made by the user to be ignored. Called when the user
203982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * decides to discard a draft.
204082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
204182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private void discardChanges() {
204282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        mTextChanged = false;
2043eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        mAttachmentsChanged = false;
204482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        mReplyFromChanged = false;
204533fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira    }
204633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira
204782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
2048181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @param body
2049181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @param save
2050181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @param showToast
2051181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @return Whether the send or save succeeded.
2052181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     */
2053181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    protected boolean sendOrSaveWithSanityChecks(final boolean save, final boolean showToast,
2054181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            final boolean orientationChanged) {
2055181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        String[] to, cc, bcc;
2056181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        Editable body = mBodyView.getEditableText();
2057181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (orientationChanged) {
2058181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            to = cc = bcc = new String[0];
2059181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        } else {
2060181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            to = getToAddresses();
2061181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            cc = getCcAddresses();
2062181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            bcc = getBccAddresses();
2063181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2064181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2065181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Don't let the user send to nobody (but it's okay to save a message
2066181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // with no recipients)
2067181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (!save && (to.length == 0 && cc.length == 0 && bcc.length == 0)) {
2068181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            showRecipientErrorDialog(getString(R.string.recipient_needed));
2069181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            return false;
2070181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2071181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2072181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        List<String> wrongEmails = new ArrayList<String>();
2073181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (!save) {
2074181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            checkInvalidEmails(to, wrongEmails);
2075181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            checkInvalidEmails(cc, wrongEmails);
2076181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            checkInvalidEmails(bcc, wrongEmails);
2077181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2078181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2079181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Don't let the user send an email with invalid recipients
2080181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (wrongEmails.size() > 0) {
2081181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            String errorText = String.format(getString(R.string.invalid_recipient),
2082181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    wrongEmails.get(0));
2083181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            showRecipientErrorDialog(errorText);
2084181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            return false;
2085181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2086181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2087181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
20880bbc858506c95005f2840fa5dff495a9216d2665Marc Blank            @Override
2089181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            public void onClick(DialogInterface dialog, int which) {
2090181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                sendOrSave(mBodyView.getEditableText(), save, showToast, orientationChanged);
2091181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            }
2092181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        };
2093181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2094181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Show a warning before sending only if there are no attachments.
2095181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (!save) {
2096181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            if (mAttachmentsView.getAttachments().isEmpty() && showEmptyTextWarnings()) {
2097181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                boolean warnAboutEmptySubject = isSubjectEmpty();
2098181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                boolean emptyBody = TextUtils.getTrimmedLength(body) == 0;
2099181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2100181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                // A warning about an empty body may not be warranted when
2101181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                // forwarding mails, since a common use case is to forward
2102181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                // quoted text and not append any more text.
2103181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                boolean warnAboutEmptyBody = emptyBody && (!mForward || isBodyEmpty());
2104181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2105181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                // When we bring up a dialog warning the user about a send,
2106181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                // assume that they accept sending the message. If they do not,
2107181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                // the dialog listener is required to enable sending again.
2108181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                if (warnAboutEmptySubject) {
2109181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    showSendConfirmDialog(R.string.confirm_send_message_with_no_subject, listener);
2110181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    return true;
2111181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                }
2112181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2113181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                if (warnAboutEmptyBody) {
2114181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    showSendConfirmDialog(R.string.confirm_send_message_with_no_body, listener);
2115181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    return true;
2116181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                }
2117181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            }
2118181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            // Ask for confirmation to send (if always required)
2119181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            if (showSendConfirmation()) {
2120181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                showSendConfirmDialog(R.string.confirm_send_message, listener);
2121181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                return true;
2122181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            }
2123181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2124181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2125181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        sendOrSave(body, save, showToast, false);
2126181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        return true;
2127181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2128181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2129181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    /**
2130181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * Returns a boolean indicating whether warnings should be shown for empty
2131181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * subject and body fields
21325c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang     *
2133181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @return True if a warning should be shown for empty text fields
2134181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     */
2135181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    protected boolean showEmptyTextWarnings() {
2136181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        return mAttachmentsView.getAttachments().size() == 0;
2137181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2138181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2139181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    /**
2140181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * Returns a boolean indicating whether the user should confirm each send
2141181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     *
2142181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @return True if a warning should be on each send
2143181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     */
2144181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    protected boolean showSendConfirmation() {
2145181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        return mCachedSettings != null ? mCachedSettings.confirmSend : false;
2146181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2147181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2148181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    private void showSendConfirmDialog(int messageId, DialogInterface.OnClickListener listener) {
2149181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (mSendConfirmDialog != null) {
2150181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            mSendConfirmDialog.dismiss();
2151181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            mSendConfirmDialog = null;
2152181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2153181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        mSendConfirmDialog = new AlertDialog.Builder(this).setMessage(messageId)
2154181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                .setTitle(R.string.confirm_send_title)
2155181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                .setIconAttribute(android.R.attr.alertDialogIcon)
2156181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                .setPositiveButton(R.string.send, listener)
21576edd597b1a6628660284f03442cce1f193af66dcMindy Pereira                .setNegativeButton(R.string.cancel, this)
21586edd597b1a6628660284f03442cce1f193af66dcMindy Pereira                .show();
2159181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2160181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2161181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    /**
2162181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * Returns whether the ComposeArea believes there is any text in the body of
2163181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * the composition. TODO: When ComposeArea controls the Body as well, add
2164181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * that here.
2165181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     */
2166181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    public boolean isBodyEmpty() {
2167181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        return !mQuotedTextView.isTextIncluded();
2168181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2169181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2170181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    /**
2171181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * Test to see if the subject is empty.
2172181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     *
2173181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * @return boolean.
2174181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     */
2175181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    // TODO: this will likely go away when composeArea.focus() is implemented
2176181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    // after all the widget control is moved over.
2177181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    public boolean isSubjectEmpty() {
2178181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        return TextUtils.getTrimmedLength(mSubject.getText()) == 0;
2179181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2180181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2181181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    /* package */
2182e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira    static int sendOrSaveInternal(Context context, ReplyFromAccount replyFromAccount,
218305b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook            Message message, final Message refMessage, Spanned body, final CharSequence quotedText,
218405b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook            SendOrSaveCallback callback, Handler handler, boolean save, int composeMode) {
218529ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira        ContentValues values = new ContentValues();
218629ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira
2187c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira        String refMessageId = refMessage != null ? refMessage.uri.toString() : "";
2188c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira
2189e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        MessageModification.putToAddresses(values, message.getToAddresses());
2190e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        MessageModification.putCcAddresses(values, message.getCcAddresses());
2191e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        MessageModification.putBccAddresses(values, message.getBccAddresses());
219229ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira
2193e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        MessageModification.putCustomFromAddress(values, message.from);
219492551d057965689f1952faeb06763f0762bc717fMindy Pereira
2195e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        MessageModification.putSubject(values, message.subject);
219629ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira        String htmlBody = Html.toHtml(body);
219705b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook
219829ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira        boolean includeQuotedText = !TextUtils.isEmpty(quotedText);
219929ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira        StringBuilder fullBody = new StringBuilder(htmlBody);
220029ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira        if (includeQuotedText) {
2201e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira            // HTML gets converted to text for now
2202e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira            final String text = quotedText.toString();
2203e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira            if (QuotedTextView.containsQuotedText(text)) {
2204e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira                int pos = QuotedTextView.getQuotedTextOffset(text);
220555271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook                final int quoteStartPos = fullBody.length() + pos;
220655271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook                fullBody.append(text);
220755271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook                MessageModification.putQuoteStartPos(values, quoteStartPos);
220812575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira                MessageModification.putForward(values, composeMode == ComposeActivity.FORWARD);
2209e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira                MessageModification.putAppendRefMessageContent(values, includeQuotedText);
221029ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira            } else {
2211e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira                LogUtils.w(LOG_TAG, "Couldn't find quoted text");
2212e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira                // This shouldn't happen, but just use what we have,
2213e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira                // and don't do server-side expansion
2214e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira                fullBody.append(text);
221529ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira            }
221629ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira        }
2217002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        int draftType = getDraftType(composeMode);
221812575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira        MessageModification.putDraftType(values, draftType);
2219c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira        if (refMessage != null) {
2220c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira            if (!TextUtils.isEmpty(refMessage.bodyHtml)) {
2221c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira                MessageModification.putBodyHtml(values, fullBody.toString());
2222c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira            }
2223c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira            if (!TextUtils.isEmpty(refMessage.bodyText)) {
2224c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira                MessageModification.putBody(values, Html.fromHtml(fullBody.toString()).toString());
2225c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira            }
2226c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira        } else {
2227c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira            MessageModification.putBodyHtml(values, fullBody.toString());
2228c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira            MessageModification.putBody(values, Html.fromHtml(fullBody.toString()).toString());
2229c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira        }
2230e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        MessageModification.putAttachments(values, message.getAttachments());
223112575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira        if (!TextUtils.isEmpty(refMessageId)) {
223212575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira            MessageModification.putRefMessageId(values, refMessageId);
223312575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira        }
223482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
223592551d057965689f1952faeb06763f0762bc717fMindy Pereira        SendOrSaveMessage sendOrSaveMessage = new SendOrSaveMessage(replyFromAccount,
2236181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                values, refMessageId, save);
2237181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        SendOrSaveTask sendOrSaveTask = new SendOrSaveTask(context, sendOrSaveMessage, callback);
223882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2239181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        callback.initializeSendOrSave(sendOrSaveTask);
224082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2241181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Do the send/save action on the specified handler to avoid possible
2242181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // ANRs
2243181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        handler.post(sendOrSaveTask);
224482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2245181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        return sendOrSaveMessage.requestId();
2246181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
224782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2248002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira    private static int getDraftType(int mode) {
2249002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        int draftType = -1;
2250002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        switch (mode) {
2251002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            case ComposeActivity.COMPOSE:
2252002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                draftType = DraftType.COMPOSE;
2253002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                break;
2254002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            case ComposeActivity.REPLY:
2255002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                draftType = DraftType.REPLY;
2256002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                break;
2257002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            case ComposeActivity.REPLY_ALL:
2258002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                draftType = DraftType.REPLY_ALL;
2259002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                break;
2260002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira            case ComposeActivity.FORWARD:
2261002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                draftType = DraftType.FORWARD;
2262002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira                break;
2263002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        }
2264002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira        return draftType;
2265002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira    }
2266002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira
2267181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    private void sendOrSave(Spanned body, boolean save, boolean showToast,
2268181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            boolean orientationChanged) {
2269181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Check if user is a monkey. Monkeys can compose and hit send
2270181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // button but are not allowed to send anything off the device.
22713ae824c79ffba25b0cda8b0300f41a28cfbfca7fPaul Westbrook        if (ActivityManager.isUserAMonkey()) {
2272181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            return;
2273181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
227482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2275181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        String[] to, cc, bcc;
2276181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (orientationChanged) {
2277181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            to = cc = bcc = new String[0];
2278181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        } else {
2279181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            to = getToAddresses();
2280181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            cc = getCcAddresses();
2281181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            bcc = getBccAddresses();
2282181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
228382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2284181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        SendOrSaveCallback callback = new SendOrSaveCallback() {
228582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            private int mRestoredRequestId;
228682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
22870bbc858506c95005f2840fa5dff495a9216d2665Marc Blank            @Override
228882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask) {
2289181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                synchronized (mActiveTasks) {
2290181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    int numTasks = mActiveTasks.size();
2291181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    if (numTasks == 0) {
2292181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                        // Start service so we won't be killed if this app is
2293181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                        // put in the background.
2294181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                        startService(new Intent(ComposeActivity.this, EmptyService.class));
2295181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    }
2296181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2297181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    mActiveTasks.add(sendOrSaveTask);
2298181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                }
2299181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                if (sTestSendOrSaveCallback != null) {
2300181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    sTestSendOrSaveCallback.initializeSendOrSave(sendOrSaveTask);
2301181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                }
2302181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            }
230382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
23040bbc858506c95005f2840fa5dff495a9216d2665Marc Blank            @Override
23057ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage,
23067ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    Message message) {
2307181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                synchronized (mDraftLock) {
2308181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    mDraftId = message.id;
2309181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    mDraft = message;
23107ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    if (sRequestMessageIdMap != null) {
23117ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                        sRequestMessageIdMap.put(sendOrSaveMessage.requestId(), mDraftId);
23127ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    }
2313181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    // Cache request message map, in case the process is killed
2314181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    saveRequestMap();
2315181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                }
2316181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                if (sTestSendOrSaveCallback != null) {
23177ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    sTestSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, message);
2318181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                }
2319181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            }
232082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
23210bbc858506c95005f2840fa5dff495a9216d2665Marc Blank            @Override
23227ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            public Message getMessage() {
23237ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                synchronized (mDraftLock) {
23247ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    return mDraft;
23257ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                }
23267ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            }
232782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
23280bbc858506c95005f2840fa5dff495a9216d2665Marc Blank            @Override
23297ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            public void sendOrSaveFinished(SendOrSaveTask task, boolean success) {
233047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                // Update the last sent from account.
233147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                if (mAccount != null) {
233247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                    MailAppProvider.getInstance().setLastSentFromAccount(mAccount.uri.toString());
233347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira                }
23347ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                if (success) {
23357ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    // Successfully sent or saved so reset change markers
23367ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    discardChanges();
23377ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                } else {
23387ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    // A failure happened with saving/sending the draft
23397ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    // TODO(pwestbro): add a better string that should be used
23407ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    // when failing to send or save
23417ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    Toast.makeText(ComposeActivity.this, R.string.send_failed, Toast.LENGTH_SHORT)
23427ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                            .show();
23437ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                }
234482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
23457ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                int numTasks;
23467ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                synchronized (mActiveTasks) {
23477ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    // Remove the task from the list of active tasks
23487ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    mActiveTasks.remove(task);
23497ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    numTasks = mActiveTasks.size();
23507ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                }
235182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
23527ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                if (numTasks == 0) {
23537ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    // Stop service so we can be killed.
23547ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    stopService(new Intent(ComposeActivity.this, EmptyService.class));
23557ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                }
23567ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                if (sTestSendOrSaveCallback != null) {
23577ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                    sTestSendOrSaveCallback.sendOrSaveFinished(task, success);
23587ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira                }
23597ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira            }
2360181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        };
2361181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2362181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Get the selected account if the from spinner has been setup.
236392551d057965689f1952faeb06763f0762bc717fMindy Pereira        ReplyFromAccount selectedAccount = mReplyFromAccount;
2364181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        String fromAddress = selectedAccount.name;
2365181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (selectedAccount == null || fromAddress == null) {
2366181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            // We don't have either the selected account or from address,
2367181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            // use mAccount.
236892551d057965689f1952faeb06763f0762bc717fMindy Pereira            selectedAccount = mReplyFromAccount;
2369181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            fromAddress = mAccount.name;
2370181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2371181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2372181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (mSendSaveTaskHandler == null) {
2373181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            HandlerThread handlerThread = new HandlerThread("Send Message Task Thread");
2374181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            handlerThread.start();
2375181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2376181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            mSendSaveTaskHandler = new Handler(handlerThread.getLooper());
2377181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2378181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2379e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira        Message msg = createMessage(mReplyFromAccount, getMode());
238005b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook        mRequestId = sendOrSaveInternal(this, mReplyFromAccount, msg, mRefMessage, body,
238105b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook                mQuotedTextView.getQuotedTextIfIncluded(), callback,
238212575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira                mSendSaveTaskHandler, save, mComposeMode);
2383181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2384181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (mRecipient != null && mRecipient.equals(mAccount.name)) {
2385181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            mRecipient = selectedAccount.name;
2386181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2387b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook        setAccount(selectedAccount.account);
2388181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2389181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Don't display the toast if the user is just changing the orientation,
2390181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // but we still need to save the draft to the cursor because this is how we restore
2391181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // the attachments when the configuration change completes.
2392181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (showToast && (getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
2393181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            Toast.makeText(this, save ? R.string.message_saved : R.string.sending_message,
2394181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                    Toast.LENGTH_LONG).show();
2395181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2396181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2397181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // Need to update variables here because the send or save completes
2398181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // asynchronously even though the toast shows right away.
2399181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        discardChanges();
2400181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        updateSaveUi();
2401181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2402181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // If we are sending, finish the activity
2403181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        if (!save) {
2404181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            finish();
2405181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        }
2406181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
2407181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira
2408181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    /**
2409181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * Save the state of the request messageid map. This allows for the Gmail
2410181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * process to be killed, but and still allow for ComposeActivity instances
2411181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     * to be recreated correctly.
2412181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira     */
2413181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    private void saveRequestMap() {
2414181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        // TODO: store the request map in user preferences.
2415181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira    }
241682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
24172db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira    private void doAttach(String type) {
2418013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
2419013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira        i.addCategory(Intent.CATEGORY_OPENABLE);
2420d6a9a3f94c69d05f23349a09d71cd36c6fb03613Paul Westbrook        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
24212db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira        i.setType(type);
2422013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira        mAddingAttachment = true;
2423181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira        startActivityForResult(Intent.createChooser(i, getText(R.string.select_attachment_type)),
2424181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                RESULT_PICK_ATTACHMENT);
2425013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira    }
2426013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira
2427ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira    private void showCcBccViews() {
2428a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        mCcBccView.show(true, true, true);
2429ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        if (mCcBccButton != null) {
2430cd0b0b950efebfc3964334067747b97e61c4f027mindyp            mCcBccButton.setVisibility(View.INVISIBLE);
2431ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira        }
2432ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira    }
2433ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira
2434326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    @Override
2435326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    public boolean onNavigationItemSelected(int position, long itemId) {
2436a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        int initialComposeMode = mComposeMode;
2437326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        if (position == ComposeActivity.REPLY) {
2438326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            mComposeMode = ComposeActivity.REPLY;
2439326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        } else if (position == ComposeActivity.REPLY_ALL) {
2440326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            mComposeMode = ComposeActivity.REPLY_ALL;
2441326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        } else if (position == ComposeActivity.FORWARD) {
2442326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            mComposeMode = ComposeActivity.FORWARD;
2443326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        }
2444cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        clearChangeListeners();
2445a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        if (initialComposeMode != mComposeMode) {
2446154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira            resetMessageForModeChange();
2447ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            if (mDraft == null && mRefMessage != null) {
244896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira                setFieldsFromRefMessage(mComposeMode, mAccount.name);
24498eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira            }
2450ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            boolean showCc = false;
2451ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            boolean showBcc = false;
2452ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            if (mDraft != null) {
2453ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                // Following desktop behavior, if the user has added a BCC
2454ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                // field to a draft, we show it regardless of compose mode.
2455ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                showBcc = !TextUtils.isEmpty(mDraft.bcc);
2456ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                // Use the draft to determine what to populate.
2457ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                // If the Bcc field is showing, show the Cc field whether it is populated or not.
2458ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                showCc = showBcc || (!TextUtils.isEmpty(mDraft.cc) && mComposeMode == REPLY_ALL);
2459ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            } else if (mRefMessage != null) {
2460ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira                showCc = mComposeMode == REPLY_ALL && !TextUtils.isEmpty(mRefMessage.cc);
2461ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            }
2462ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira            mCcBccView.show(false, showCc, showBcc);
2463a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira        }
2464ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira        updateHideOrShowCcBcc();
2465cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira        initChangeListeners();
2466326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        return true;
2467326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    }
2468326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
2469b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira    @VisibleForTesting
2470b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira    protected void resetMessageForModeChange() {
2471154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // When switching between reply, reply all, forward,
2472154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // follow the behavior of webview.
2473154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // The contents of the following fields are cleared
2474154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // so that they can be populated directly from the
2475154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // ref message:
2476154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // 1) Any recipient fields
2477154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // 2) The subject
2478154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        mTo.setText("");
2479154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        mCc.setText("");
2480154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        mBcc.setText("");
2481154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // Any edits to the subject are replaced with the original subject.
2482154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        mSubject.setText("");
2483154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira
2484154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // Any changes to the contents of the following fields are kept:
2485154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // 1) Body
2486154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // 2) Attachments
2487154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        // If the user made changes to attachments, keep their changes.
2488154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        if (!mAttachmentsChanged) {
2489154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira            mAttachmentsView.deleteAllAttachments();
2490154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira        }
2491154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira    }
2492154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira
2493326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    private class ComposeModeAdapter extends ArrayAdapter<String> {
2494326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
2495326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        private LayoutInflater mInflater;
2496326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
2497326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        public ComposeModeAdapter(Context context) {
2498326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            super(context, R.layout.compose_mode_item, R.id.mode, getResources()
2499326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                    .getStringArray(R.array.compose_modes));
2500326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        }
2501326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
2502326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        private LayoutInflater getInflater() {
2503326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            if (mInflater == null) {
2504326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                mInflater = LayoutInflater.from(getContext());
2505326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            }
2506326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            return mInflater;
2507326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        }
2508326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira
2509326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        @Override
2510326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        public View getView(int position, View convertView, ViewGroup parent) {
2511326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            if (convertView == null) {
2512326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira                convertView = getInflater().inflate(R.layout.compose_mode_display_item, null);
2513326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            }
2514326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            ((TextView) convertView.findViewById(R.id.mode)).setText(getItem(position));
2515326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira            return super.getView(position, convertView, parent);
2516326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira        }
2517326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira    }
251846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
251946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    @Override
252046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    public void onRespondInline(String text) {
252146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        appendToBody(text, false);
252240882430c874ff29890ec6fa31f7649788cbc470mindyp        mQuotedTextView.setUpperDividerVisible(false);
252340882430c874ff29890ec6fa31f7649788cbc470mindyp        mTo.requestFocus();
252446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
252546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
252646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    /**
252746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * Append text to the body of the message. If there is no existing body
252846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * text, just sets the body to text.
252946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     *
253046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * @param text
253146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * @param withSignature True to append a signature.
253246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     */
253346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    public void appendToBody(CharSequence text, boolean withSignature) {
2534eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        Editable bodyText = mBodyView.getEditableText();
253546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        if (bodyText != null && bodyText.length() > 0) {
253646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            bodyText.append(text);
253746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        } else {
253846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira            setBody(text, withSignature);
253946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira        }
254046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
254146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira
254246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    /**
254346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * Set the body of the message.
2544bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira     *
254546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * @param text
254646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     * @param withSignature True to append a signature.
254746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira     */
254846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    public void setBody(CharSequence text, boolean withSignature) {
2549eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        mBodyView.setText(text);
2550bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        if (withSignature) {
2551bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira            appendSignature();
2552bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        }
2553bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    }
2554bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira
2555bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    private void appendSignature() {
2556b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira        String newSignature = mCachedSettings != null ? mCachedSettings.signature : null;
2557433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira        boolean hasFocus = mBodyView.hasFocus();
2558b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira        if (!TextUtils.equals(newSignature, mSignature)) {
2559b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira            mSignature = newSignature;
2560b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira            if (!TextUtils.isEmpty(mSignature)
2561b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira                    && getSignatureStartPosition(mSignature,
2562b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira                            mBodyView.getText().toString()) < 0) {
2563b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira                // Appending a signature does not count as changing text.
2564b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira                mBodyView.removeTextChangedListener(this);
2565b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira                mBodyView.append(convertToPrintableSignature(mSignature));
2566b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira                mBodyView.addTextChangedListener(this);
2567b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira            }
2568433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            if (hasFocus) {
2569433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira                focusBody();
2570433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira            }
2571bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        }
2572bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    }
2573bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira
2574bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira    private String convertToPrintableSignature(String signature) {
2575bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        String signatureResource = getResources().getString(R.string.signature);
2576bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        if (signature == null) {
2577bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira            signature = "";
2578bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        }
2579bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira        return String.format(signatureResource, signature);
258046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira    }
25811a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira
25825a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira    @Override
25835a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira    public void onAccountChanged() {
258492551d057965689f1952faeb06763f0762bc717fMindy Pereira        mReplyFromAccount = mFromSpinner.getCurrentAccount();
258592551d057965689f1952faeb06763f0762bc717fMindy Pereira        if (!mAccount.equals(mReplyFromAccount.account)) {
2586b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook            setAccount(mReplyFromAccount.account);
2587b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook
2588181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            // TODO: handle discarding attachments when switching accounts.
2589181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            // Only enable save for this draft if there is any other content
2590181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            // in the message.
2591181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            if (!isBlank()) {
2592181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira                enableSave(true);
2593181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            }
2594181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            mReplyFromChanged = true;
2595181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira            initRecipients();
259682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
25971a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira    }
259882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
259982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public void enableSave(boolean enabled) {
260082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (mSave != null) {
260182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSave.setEnabled(enabled);
260282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
260382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
260482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
260582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public void enableSend(boolean enabled) {
260682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (mSend != null) {
260782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            mSend.setEnabled(enabled);
260882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
260982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
261082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
261182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
261282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Handles button clicks from any error dialogs dealing with sending
261382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * a message.
261482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
261582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    @Override
261682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    public void onClick(DialogInterface dialog, int which) {
261782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        switch (which) {
261882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            case DialogInterface.BUTTON_POSITIVE: {
261982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                doDiscardWithoutConfirmation(true /* show toast */ );
262082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                break;
262182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
262282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            case DialogInterface.BUTTON_NEGATIVE: {
262382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                // If the user cancels the send, re-enable the send button.
262482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                enableSend(true);
262582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                break;
262682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
262782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
262882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
262982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
263082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2631efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira    private void doDiscard() {
2632efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira        new AlertDialog.Builder(this).setMessage(R.string.confirm_discard_text)
2633efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira                .setPositiveButton(R.string.ok, this)
2634efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira                .setNegativeButton(R.string.cancel, null)
2635efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira                .create().show();
2636efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira    }
263782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    /**
263882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * Effectively discard the current message.
263982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     *
264082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * This method is either invoked from the menu or from the dialog
264182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * once the user has confirmed that they want to discard the message.
264282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     * @param showToast show "Message discarded" toast if true
264382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira     */
264482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    private void doDiscardWithoutConfirmation(boolean showToast) {
26457ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira        synchronized (mDraftLock) {
264682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            if (mDraftId != UIProvider.INVALID_MESSAGE_ID) {
264782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                ContentValues values = new ContentValues();
2648b7050e62aab7133dea300d7fb3266311da99ec80Paul Westbrook                values.put(BaseColumns._ID, mDraftId);
264978ea8e20c7d678c79153a1f814d0740f2bf3e462Marc Blank                if (!mAccount.expungeMessageUri.equals(Uri.EMPTY)) {
2650cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                    getContentResolver().update(mAccount.expungeMessageUri, values, null, null);
2651cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                } else {
26520bbc858506c95005f2840fa5dff495a9216d2665Marc Blank                    getContentResolver().delete(mDraft.uri, null, null);
2653cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira                }
265482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                // This is not strictly necessary (since we should not try to
265582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                // save the draft after calling this) but it ensures that if we
265682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                // do save again for some reason we make a new draft rather than
265782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                // trying to resave an expunged draft.
265882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira                mDraftId = UIProvider.INVALID_MESSAGE_ID;
265982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            }
266082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
266182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
266282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        if (showToast) {
266382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            // Display a toast to let the user know
266482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira            Toast.makeText(this, R.string.message_discarded, Toast.LENGTH_SHORT).show();
266582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        }
266682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
266782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        // This prevents the draft from being saved in onPause().
266882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        discardChanges();
266982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira        finish();
267082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira    }
267182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira
2672eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    private void saveIfNeeded() {
2673eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        if (mAccount == null) {
2674eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            // We have not chosen an account yet so there's no way that we can save. This is ok,
2675eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            // though, since we are saving our state before AccountsActivity is activated. Thus, the
2676eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            // user has not interacted with us yet and there is no real state to save.
2677eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira            return;
2678eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        }
2679eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
2680eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        if (shouldSave()) {
268148e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira            doSave(!mAddingAttachment /* show toast */);
2682eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        }
2683eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
2684eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira
2685eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    @Override
2686eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    public void onAttachmentDeleted() {
2687eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        mAttachmentsChanged = true;
268840882430c874ff29890ec6fa31f7649788cbc470mindyp        // If we are showing any attachments, make sure we have an upper
268940882430c874ff29890ec6fa31f7649788cbc470mindyp        // divider.
269040882430c874ff29890ec6fa31f7649788cbc470mindyp        mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0);
2691eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira        updateSaveUi();
2692eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira    }
269375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
269440882430c874ff29890ec6fa31f7649788cbc470mindyp    @Override
269540882430c874ff29890ec6fa31f7649788cbc470mindyp    public void onAttachmentAdded() {
269640882430c874ff29890ec6fa31f7649788cbc470mindyp        mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0);
269740882430c874ff29890ec6fa31f7649788cbc470mindyp        mAttachmentsView.focusLastAttachment();
269840882430c874ff29890ec6fa31f7649788cbc470mindyp    }
269975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
270075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    /**
270175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira     * This is called any time one of our text fields changes.
270275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira     */
27030bbc858506c95005f2840fa5dff495a9216d2665Marc Blank    @Override
270475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    public void afterTextChanged(Editable s) {
270575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        mTextChanged = true;
270675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        updateSaveUi();
270775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    }
270875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
270975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    @Override
271075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
271175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        // Do nothing.
271275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    }
271375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
27140bbc858506c95005f2840fa5dff495a9216d2665Marc Blank    @Override
271575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    public void onTextChanged(CharSequence s, int start, int before, int count) {
271675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        // Do nothing.
271775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    }
271875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
271975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
272075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    // There is a big difference between the text associated with an address changing
272175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    // to add the display name or to format properly and a recipient being added or deleted.
272275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    // Make sure we only notify of changes when a recipient has been added or deleted.
272375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    private class RecipientTextWatcher implements TextWatcher {
272475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        private HashMap<String, Integer> mContent = new HashMap<String, Integer>();
272575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
272675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        private RecipientEditTextView mView;
272775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
272875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        private TextWatcher mListener;
272975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
273075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        public RecipientTextWatcher(RecipientEditTextView view, TextWatcher listener) {
273175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            mView = view;
273275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            mListener = listener;
273375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
273475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
273575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        @Override
273675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        public void afterTextChanged(Editable s) {
273775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            if (hasChanged()) {
273875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                mListener.afterTextChanged(s);
273975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            }
274075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
274175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
274275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        private boolean hasChanged() {
274375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            String[] currRecips = tokenizeRecips(getAddressesFromList(mView));
274475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            int totalCount = currRecips.length;
274575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            int totalPrevCount = 0;
274675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            for (Entry<String, Integer> entry : mContent.entrySet()) {
274775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                totalPrevCount += entry.getValue();
274875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            }
274975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            if (totalCount != totalPrevCount) {
275075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                return true;
275175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            }
275275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
275375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            for (String recip : currRecips) {
275475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                if (!mContent.containsKey(recip)) {
275575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    return true;
275675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                } else {
275775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    int count = mContent.get(recip) - 1;
275875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    if (count < 0) {
275975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                        return true;
276075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    } else {
276175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                        mContent.put(recip, count);
276275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    }
276375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                }
276475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            }
276575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            return false;
276675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
276775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
276875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        private String[] tokenizeRecips(String[] recips) {
276975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            // Tokenize them all and put them in the list.
277075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            String[] recipAddresses = new String[recips.length];
277175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            for (int i = 0; i < recips.length; i++) {
277275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                recipAddresses[i] = Rfc822Tokenizer.tokenize(recips[i])[0].getAddress();
277375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            }
277475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            return recipAddresses;
277575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
277675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
277775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        @Override
277875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
277975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            String[] recips = tokenizeRecips(getAddressesFromList(mView));
278075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            for (String recip : recips) {
278175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                if (!mContent.containsKey(recip)) {
278275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    mContent.put(recip, 1);
278375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                } else {
278475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                    mContent.put(recip, (mContent.get(recip)) + 1);
278575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira                }
278675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            }
278775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
278875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira
278975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        @Override
279075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        public void onTextChanged(CharSequence s, int start, int before, int count) {
279175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira            // Do nothing.
279275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira        }
279375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira    }
2794e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira
2795e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    public static void registerTestSendOrSaveCallback(SendOrSaveCallback testCallback) {
2796e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        if (sTestSendOrSaveCallback != null && testCallback != null) {
2797e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira            throw new IllegalStateException("Attempting to register more than one test callback");
2798e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        }
2799e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira        sTestSendOrSaveCallback = testCallback;
2800e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira    }
2801bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira
2802bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira    @VisibleForTesting
2803bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira    protected ArrayList<Attachment> getAttachments() {
2804bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira        return mAttachmentsView.getAttachments();
2805bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira    }
280696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira
280796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    @Override
280896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
280996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        switch (id) {
281096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira            case REFERENCE_MESSAGE_LOADER:
281196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira                return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null,
281296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira                        null, null);
2813b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            case LOADER_ACCOUNT_CURSOR:
2814b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                return new CursorLoader(this, MailAppProvider.getAccountsUri(),
2815b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        UIProvider.ACCOUNTS_PROJECTION, null, null, null);
281696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        }
281796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        return null;
281896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    }
281996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira
282096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    @Override
282196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
2822b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        int id = loader.getId();
2823b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        switch (id) {
2824b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            case REFERENCE_MESSAGE_LOADER:
2825b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                if (data != null && data.moveToFirst()) {
2826b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    mRefMessage = new Message(data);
2827b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    // We set these based on EXTRA_TO.
2828b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    mRefMessage.to = null;
2829b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    mRefMessage.from = null;
2830b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    Intent intent = getIntent();
2831b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE);
2832b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    initFromRefMessage(action, mAccount.name);
2833b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    finishSetup(action, intent, null, true);
2834b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    if (action != FORWARD) {
2835b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        String to = intent.getStringExtra(EXTRA_TO);
2836b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        if (!TextUtils.isEmpty(to)) {
2837b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                            clearChangeListeners();
2838b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                            mTo.append(to);
2839b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                            initChangeListeners();
2840b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        }
2841b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    }
2842b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                } else {
2843b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    finish();
284496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira                }
2845b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                break;
2846b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            case LOADER_ACCOUNT_CURSOR:
2847b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                if (data != null && data.moveToFirst()) {
2848b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    // there are accounts now!
2849b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    Account account;
2850b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    ArrayList<Account> accounts = new ArrayList<Account>();
2851b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    ArrayList<Account> initializedAccounts = new ArrayList<Account>();
2852b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    do {
2853b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        account = new Account(data);
2854b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        if (account.isAccountIntialized()) {
2855b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                            initializedAccounts.add(account);
2856b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        }
2857b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        accounts.add(account);
2858b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    } while (data.moveToNext());
2859b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    if (initializedAccounts.size() > 0) {
2860b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        findViewById(R.id.wait).setVisibility(View.GONE);
2861b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        getLoaderManager().destroyLoader(LOADER_ACCOUNT_CURSOR);
2862b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        findViewById(R.id.compose).setVisibility(View.VISIBLE);
2863b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        mAccounts = accounts.toArray(new Account[initializedAccounts.size()]);
2864b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        finishCreate();
2865b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        invalidateOptionsMenu();
2866b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    } else {
2867b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        // Show "waiting"
2868b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        account = accounts.size() > 0 ? accounts.get(0) : null;
2869b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                        showWaitFragment(account);
2870b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    }
2871b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                }
2872b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                break;
2873b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        }
2874b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    }
2875b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira
2876b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private void showWaitFragment(Account account) {
2877b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        WaitFragment fragment = getWaitFragment();
2878b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        if (fragment != null) {
2879b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            fragment.updateAccount(account);
288096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        } else {
2881b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            findViewById(R.id.wait).setVisibility(View.VISIBLE);
2882b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira            replaceFragment(WaitFragment.newInstance(account, true),
2883b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira                    FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT);
288496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        }
288596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    }
288696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira
2887b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private WaitFragment getWaitFragment() {
2888b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        return (WaitFragment) getFragmentManager().findFragmentByTag(TAG_WAIT);
2889b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    }
2890b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira
2891b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    private int replaceFragment(Fragment fragment, int transition, String tag) {
2892b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
2893b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        fragmentTransaction.addToBackStack(null);
2894b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        fragmentTransaction.setTransition(transition);
2895b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        fragmentTransaction.replace(R.id.wait, fragment, tag);
2896b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        final int transactionId = fragmentTransaction.commitAllowingStateLoss();
2897b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira        return transactionId;
2898b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira    }
2899b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira
290096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    @Override
290196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    public void onLoaderReset(Loader<Cursor> arg0) {
290296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira        // Do nothing.
290396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira    }
290496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira}