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