14aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein/*
24aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * Copyright (C) 2012 Google Inc.
34aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * Licensed to The Android Open Source Project.
44aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein *
54aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
64aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * you may not use this file except in compliance with the License.
74aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * You may obtain a copy of the License at
84aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein *
94aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein *      http://www.apache.org/licenses/LICENSE-2.0
104aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein *
114aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software
124aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
134aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * See the License for the specific language governing permissions and
154aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * limitations under the License.
164aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein */
174aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
184aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinpackage com.android.mail.browse;
194aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
204aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.app.AlertDialog;
218081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrookimport android.app.FragmentManager;
224aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.content.ActivityNotFoundException;
234aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.content.Context;
244aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.content.Intent;
252fd167d6131482da984768b5ee75cefa32ed3e32Andrew Sappersteinimport android.support.v4.text.BidiFormatter;
264aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.text.TextUtils;
274aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.util.AttributeSet;
284aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.view.LayoutInflater;
294aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.view.Menu;
304aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.view.MenuItem;
314aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.view.View;
324aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.view.View.OnClickListener;
334aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.view.ViewGroup;
34e18f42d652e171cd4e4bb193482d2e131d91f26eMark Weiimport android.widget.FrameLayout;
354c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sappersteinimport android.widget.ImageButton;
364aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.widget.ImageView;
374aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.widget.PopupMenu;
384aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.widget.PopupMenu.OnMenuItemClickListener;
394aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.widget.ProgressBar;
404aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport android.widget.TextView;
414aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
424aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.R;
43e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huangimport com.android.mail.analytics.Analytics;
44f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sappersteinimport com.android.mail.providers.Account;
454aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.providers.Attachment;
464aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.providers.UIProvider.AttachmentDestination;
474aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.providers.UIProvider.AttachmentState;
48f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sappersteinimport com.android.mail.ui.AccountFeedbackActivity;
494aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.utils.AttachmentUtils;
50b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
514aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.utils.LogUtils;
524aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.utils.MimeType;
534aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sappersteinimport com.android.mail.utils.Utils;
544cb51dbce9635f4bf68a6de88f759e2f86d20325Andrew Sapperstein
554aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein/**
564aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * View for a single attachment in conversation view. Shows download status and allows launching
574aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein * intents to act on an attachment.
584aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein *
594aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein */
60e18f42d652e171cd4e4bb193482d2e131d91f26eMark Weipublic class MessageAttachmentBar extends FrameLayout implements OnClickListener,
614aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        OnMenuItemClickListener, AttachmentViewInterface {
624aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
634aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private Attachment mAttachment;
644aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private TextView mTitle;
654aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private TextView mSubTitle;
664aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private String mAttachmentSizeText;
674aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private String mDisplayType;
684aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private ProgressBar mProgress;
694c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein    private ImageButton mCancelButton;
704aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private PopupMenu mPopup;
714aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private ImageView mOverflowButton;
724aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
734aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private final AttachmentActionHandler mActionHandler;
74c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein    private boolean mSaveClicked;
75f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein    private Account mAccount;
764aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
7774313d9a9ea22d21658e805600f114a78a2fb935Mark Wei    private final Runnable mUpdateRunnable = new Runnable() {
7874313d9a9ea22d21658e805600f114a78a2fb935Mark Wei            @Override
7974313d9a9ea22d21658e805600f114a78a2fb935Mark Wei        public void run() {
8074313d9a9ea22d21658e805600f114a78a2fb935Mark Wei            updateActionsInternal();
8174313d9a9ea22d21658e805600f114a78a2fb935Mark Wei        }
8274313d9a9ea22d21658e805600f114a78a2fb935Mark Wei    };
8374313d9a9ea22d21658e805600f114a78a2fb935Mark Wei
84b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    private static final String LOG_TAG = LogTag.getLogTag();
854aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
86833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein    /**
87833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein     * Boolean used to tell whether extra option 1 should always be hidden.
88833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein     * Currently makes sure that there is no conversation because that state
89833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein     * means that we're in the EML viewer.
90833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein     */
91833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein    private boolean mHideExtraOptionOne;
92833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein
937638a1004e7c8ed7a85620243da3b051b60217e8Andrew Sapperstein
944aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public MessageAttachmentBar(Context context) {
954aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        this(context, null);
964aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
974aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
984aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public MessageAttachmentBar(Context context, AttributeSet attrs) {
994aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        super(context, attrs);
1004aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1014aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mActionHandler = new AttachmentActionHandler(context, this);
1024aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
1034aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1048081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook    public void initialize(FragmentManager fragmentManager) {
1058081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook        mActionHandler.initialize(fragmentManager);
1068081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook    }
1078081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook
1084aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public static MessageAttachmentBar inflate(LayoutInflater inflater, ViewGroup parent) {
1094aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        MessageAttachmentBar view = (MessageAttachmentBar) inflater.inflate(
1104aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                R.layout.conversation_message_attachment_bar, parent, false);
1114aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        return view;
1124aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
1134aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1144aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    /**
1154aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein     * Render or update an attachment's view. This happens immediately upon instantiation, and
1164aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein     * repeatedly as status updates stream in, so only properties with new or changed values will
1174aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein     * cause sub-views to update.
1184aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein     */
1194f347e811052f446c3958c76db278bcd7b39a44fAndy Huang    public void render(Attachment attachment, Account account, ConversationMessage message,
1202fd167d6131482da984768b5ee75cefa32ed3e32Andrew Sapperstein            boolean loaderResult, BidiFormatter bidiFormatter) {
1217638a1004e7c8ed7a85620243da3b051b60217e8Andrew Sapperstein        // get account uri for potential eml viewer usage
122f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        mAccount = account;
1237638a1004e7c8ed7a85620243da3b051b60217e8Andrew Sapperstein
1244aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        final Attachment prevAttachment = mAttachment;
1254aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mAttachment = attachment;
126a2519e3a1444b8421261348279883108ad1d00beGreg Bullock        if (mAccount != null) {
127a2519e3a1444b8421261348279883108ad1d00beGreg Bullock            mActionHandler.setAccount(mAccount.getEmailAddress());
128a2519e3a1444b8421261348279883108ad1d00beGreg Bullock        }
1294f347e811052f446c3958c76db278bcd7b39a44fAndy Huang        mActionHandler.setMessage(message);
1304aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mActionHandler.setAttachment(mAttachment);
131833123d9c31b0b2dd23f7f74738c5bccf8a546d3Andrew Sapperstein        mHideExtraOptionOne = message.getConversation() == null;
1324aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
133c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein        // reset mSaveClicked if we are not currently downloading
134c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein        // So if the download fails or the download completes, we stop
135c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein        // showing progress, etc
136c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein        mSaveClicked = !attachment.isDownloading() ? false : mSaveClicked;
137c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein
1384aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        LogUtils.d(LOG_TAG, "got attachment list row: name=%s state/dest=%d/%d dled=%d" +
139519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                " contentUri=%s MIME=%s flags=%d", attachment.getName(), attachment.state,
1404aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                attachment.destination, attachment.downloadedSize, attachment.contentUri,
141519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                attachment.getContentType(), attachment.flags);
1424aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1437348cf23d9df1ea3c58674b2c67d8219a6094fcfAndrew Sapperstein        final String attachmentName = attachment.getName();
144519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon        if ((attachment.flags & Attachment.FLAG_DUMMY_ATTACHMENT) != 0) {
145519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon            mTitle.setText(R.string.load_attachment);
146519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon        } else if (prevAttachment == null
1477348cf23d9df1ea3c58674b2c67d8219a6094fcfAndrew Sapperstein                || !TextUtils.equals(attachmentName, prevAttachment.getName())) {
148f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein            mTitle.setText(attachmentName);
1494aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        }
1504aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1514aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        if (prevAttachment == null || attachment.size != prevAttachment.size) {
1522fd167d6131482da984768b5ee75cefa32ed3e32Andrew Sapperstein            mAttachmentSizeText = bidiFormatter.unicodeWrap(
1532fd167d6131482da984768b5ee75cefa32ed3e32Andrew Sapperstein                    AttachmentUtils.convertToHumanReadableSize(getContext(), attachment.size));
1542fd167d6131482da984768b5ee75cefa32ed3e32Andrew Sapperstein            mDisplayType = bidiFormatter.unicodeWrap(
1552fd167d6131482da984768b5ee75cefa32ed3e32Andrew Sapperstein                    AttachmentUtils.getDisplayType(getContext(), attachment));
156c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei            updateSubtitleText();
1574aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        }
1584aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1594aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        updateActions();
1608081df46ef5a7794374e41cd1836e778a2da9b31Paul Westbrook        mActionHandler.updateStatus(loaderResult);
1614aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
1624aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1634aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    @Override
1644aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    protected void onFinishInflate() {
1654aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        super.onFinishInflate();
1664aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1674aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mTitle = (TextView) findViewById(R.id.attachment_title);
1684aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mSubTitle = (TextView) findViewById(R.id.attachment_subtitle);
1694aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mProgress = (ProgressBar) findViewById(R.id.attachment_progress);
1704aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mOverflowButton = (ImageView) findViewById(R.id.overflow);
1714c7d8b5f38bfa80192d457025b834c975d7d38a3Andrew Sapperstein        mCancelButton = (ImageButton) findViewById(R.id.cancel_attachment);
1724aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1734aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        setOnClickListener(this);
1744aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mOverflowButton.setOnClickListener(this);
1754aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mCancelButton.setOnClickListener(this);
1764aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
1774aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1784aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    @Override
1794aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public void onClick(View v) {
1804aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        onClick(v.getId(), v);
1814aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
1824aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1834aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    @Override
1844aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public boolean onMenuItemClick(MenuItem item) {
1854aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mPopup.dismiss();
1864aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        return onClick(item.getItemId(), null);
1874aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
1884aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
1892b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy    private boolean onClick(final int res, final View v) {
1902b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        if (res == R.id.preview_attachment) {
1912b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            previewAttachment();
1922b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else if (res == R.id.save_attachment) {
1932b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            if (mAttachment.canSave()) {
1942b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                mActionHandler.startDownloadingAttachment(AttachmentDestination.EXTERNAL);
1952b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                mSaveClicked = true;
196e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
197e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                Analytics.getInstance().sendEvent(
198e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                        "save_attachment", Utils.normalizeMimeType(mAttachment.getContentType()),
199e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                        "attachment_bar", mAttachment.size);
2002b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            }
2012b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else if (res == R.id.download_again) {
2022b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            if (mAttachment.isPresentLocally()) {
203ce9db80cf997f99b8c5d0ef8d22b074555aaf795Mark Wei                mActionHandler.showDownloadingDialog();
2042b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                mActionHandler.startRedownloadingAttachment(mAttachment);
205e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
206e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                Analytics.getInstance().sendEvent("redownload_attachment",
207e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                        Utils.normalizeMimeType(mAttachment.getContentType()), "attachment_bar",
208e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                        mAttachment.size);
2092b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            }
2102b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else if (res == R.id.cancel_attachment) {
2112b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            mActionHandler.cancelAttachment();
2122b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            mSaveClicked = false;
213e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
214e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang            Analytics.getInstance().sendEvent(
215e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                    "cancel_attachment", Utils.normalizeMimeType(mAttachment.getContentType()),
216e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                    "attachment_bar", mAttachment.size);
2174f347e811052f446c3958c76db278bcd7b39a44fAndy Huang        } else if (res == R.id.attachment_extra_option1) {
2184f347e811052f446c3958c76db278bcd7b39a44fAndy Huang            mActionHandler.handleOption1();
2192b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else if (res == R.id.overflow) {
2202b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // If no overflow items are visible, just bail out.
2212b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // We shouldn't be able to get here anyhow since the overflow
2222b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // button should be hidden.
2232b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            if (shouldShowOverflow()) {
2244aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                if (mPopup == null) {
2254aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                    mPopup = new PopupMenu(getContext(), v);
2264aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                    mPopup.getMenuInflater().inflate(R.menu.message_footer_overflow_menu,
2274aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                            mPopup.getMenu());
2284aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                    mPopup.setOnMenuItemClickListener(this);
2294aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                }
2304aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
2314aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                final Menu menu = mPopup.getMenu();
232856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei                menu.findItem(R.id.preview_attachment).setVisible(shouldShowPreview());
233856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei                menu.findItem(R.id.save_attachment).setVisible(shouldShowSave());
234856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei                menu.findItem(R.id.download_again).setVisible(shouldShowDownloadAgain());
2354f347e811052f446c3958c76db278bcd7b39a44fAndy Huang                menu.findItem(R.id.attachment_extra_option1).setVisible(shouldShowExtraOption1());
2364aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
2374aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                mPopup.show();
2384aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            }
2392b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy        } else {
2402b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // Handles clicking the attachment
2412b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // in any area that is not the overflow
2422b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // button or cancel button or one of the
2432b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // overflow items.
244e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang            final String mime = Utils.normalizeMimeType(mAttachment.getContentType());
245e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang            final String action;
246e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
247519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon            if ((mAttachment.flags & Attachment.FLAG_DUMMY_ATTACHMENT) != 0) {
248519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                // This is a dummy. We need to download it, but not attempt to open or preview.
249519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                mActionHandler.showDownloadingDialog();
250519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                mActionHandler.setViewOnFinish(false);
251519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                mActionHandler.startDownloadingAttachment(AttachmentDestination.CACHE);
252519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon
253519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                action = null;
254519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon            }
2552b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // If we can install, install.
2562b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            else if (MimeType.isInstallable(mAttachment.getContentType())) {
2572b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                // Save to external because the package manager only handles
2582b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                // file:// uris not content:// uris. We do the same
2592b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                // workaround in
2602b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                // UiProvider#getUiAttachmentsCursorForUIAttachments()
2612b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                mActionHandler.showAttachment(AttachmentDestination.EXTERNAL);
262e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
263e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                action = "attachment_bar_install";
2642b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            }
2652b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // If we can view or play with an on-device app,
2662b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // view or play.
2672b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            else if (MimeType.isViewable(
2682b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                    getContext(), mAttachment.contentUri, mAttachment.getContentType())) {
2692b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                mActionHandler.showAttachment(AttachmentDestination.CACHE);
270e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
271e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                action = "attachment_bar";
2722b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            }
2732b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // If we can only preview the attachment, preview.
2742b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            else if (mAttachment.canPreview()) {
2752b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                previewAttachment();
276e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
277e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                action = null;
2782b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            }
2792b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            // Otherwise, if we cannot do anything, show the info dialog.
2802b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            else {
2812b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
2822b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                int dialogMessage = R.string.no_application_found;
2832b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                builder.setTitle(R.string.more_info_attachment)
2842b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                       .setMessage(dialogMessage)
2852b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy                       .show();
286e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
287e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                action = "attachment_bar_no_viewer";
288e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang            }
289e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
290e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang            if (action != null) {
291e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                Analytics.getInstance()
292e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                        .sendEvent("view_attachment", mime, action, mAttachment.size);
2932b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy            }
2944aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        }
2954aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
2964aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        return true;
2974aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
2984aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
299856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    private boolean shouldShowPreview() {
300856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei        // state could be anything
301856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei        return mAttachment.canPreview();
302856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    }
303856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei
304856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    private boolean shouldShowSave() {
305856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei        return mAttachment.canSave() && !mSaveClicked;
306856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    }
307856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei
308856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    private boolean shouldShowDownloadAgain() {
309b5ef9a9497aeef6ccff95ce4f1e2e43912e3fcc4Mark Wei        // implies state == SAVED || state == FAILED
3107434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        // and the attachment supports re-download
3117434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        return mAttachment.supportsDownloadAgain() && mAttachment.isDownloadFinishedOrFailed();
312856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    }
313856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei
3144f347e811052f446c3958c76db278bcd7b39a44fAndy Huang    private boolean shouldShowExtraOption1() {
315aa4c9941269cc7815dd80e649e24d0257f83d5d5Alex Gawley        return !mHideExtraOptionOne &&
316aa4c9941269cc7815dd80e649e24d0257f83d5d5Alex Gawley                mActionHandler.shouldShowExtraOption1(mAttachment.getContentType());
3174f347e811052f446c3958c76db278bcd7b39a44fAndy Huang    }
3184f347e811052f446c3958c76db278bcd7b39a44fAndy Huang
319856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    private boolean shouldShowOverflow() {
320aa4c9941269cc7815dd80e649e24d0257f83d5d5Alex Gawley        return (shouldShowPreview() || shouldShowSave() || shouldShowDownloadAgain() ||
321aa4c9941269cc7815dd80e649e24d0257f83d5d5Alex Gawley                shouldShowExtraOption1()) && !shouldShowCancel();
322856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    }
323856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei
324856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    private boolean shouldShowCancel() {
325856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei        return mAttachment.isDownloading() && mSaveClicked;
326856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei    }
327856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei
328c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei    @Override
3294aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public void viewAttachment() {
330591eb37fb6db41f014626d0df51e7dc055d07af0Paul Westbrook        if (mAttachment.contentUri == null) {
331591eb37fb6db41f014626d0df51e7dc055d07af0Paul Westbrook            LogUtils.e(LOG_TAG, "viewAttachment with null content uri");
332591eb37fb6db41f014626d0df51e7dc055d07af0Paul Westbrook            return;
333591eb37fb6db41f014626d0df51e7dc055d07af0Paul Westbrook        }
334591eb37fb6db41f014626d0df51e7dc055d07af0Paul Westbrook
3354aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        Intent intent = new Intent(Intent.ACTION_VIEW);
3364aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
3374aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein                | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3388d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein
3398d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein        final String contentType = mAttachment.getContentType();
340bf3a5c5aa46759a238b3ca197b97bc4182cba8b6Mark Wei        Utils.setIntentDataAndTypeAndNormalize(
3418d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein                intent, mAttachment.contentUri, contentType);
3428d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein
3438d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein        // For EML files, we want to open our dedicated
3448d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein        // viewer rather than let any activity open it.
3458d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein        if (MimeType.isEmlMimeType(contentType)) {
3461b8d42f7d1711664a0bb0de0a8585ada6c24ffadRay Chen            intent.setPackage(getContext().getPackageName());
347f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein            intent.putExtra(AccountFeedbackActivity.EXTRA_ACCOUNT_URI,
348f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein                    mAccount != null ? mAccount.uri : null);
3498d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein        }
3508d4791ce70b3f71cc90256bc4b5b236379b56331Andrew Sapperstein
3514aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        try {
3524aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            getContext().startActivity(intent);
3534aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        } catch (ActivityNotFoundException e) {
3544aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            // couldn't find activity for View intent
355591eb37fb6db41f014626d0df51e7dc055d07af0Paul Westbrook            LogUtils.e(LOG_TAG, e, "Couldn't find Activity for intent");
3564aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        }
3574aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
3584aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
3594aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private void previewAttachment() {
360d6318e56adadeff4106e9696b5330239175487b1Andrew Sapperstein        if (mAttachment.canPreview()) {
361d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook            final Intent previewIntent =
362d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook                    new Intent(Intent.ACTION_VIEW, mAttachment.previewIntentUri);
363d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook            getContext().startActivity(previewIntent);
364e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang
365e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang            Analytics.getInstance().sendEvent(
366e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                    "preview_attachment", Utils.normalizeMimeType(mAttachment.getContentType()),
367e003b4cc4a23e6d394998bebe26430a361c5ac29Andy Huang                    null, mAttachment.size);
368d49db8e3c4fff459f4ae3869ea80d083461eda2cPaul Westbrook        }
3694aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
3704aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
3713b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy    private static void setButtonVisible(View button, boolean visible) {
3724aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        button.setVisibility(visible ? VISIBLE : GONE);
3734aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
3744aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
3754aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    /**
3764aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein     * Update all actions based on current downloading state.
3774aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein     */
3784aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    private void updateActions() {
37974313d9a9ea22d21658e805600f114a78a2fb935Mark Wei        removeCallbacks(mUpdateRunnable);
38074313d9a9ea22d21658e805600f114a78a2fb935Mark Wei        post(mUpdateRunnable);
38174313d9a9ea22d21658e805600f114a78a2fb935Mark Wei    }
38274313d9a9ea22d21658e805600f114a78a2fb935Mark Wei
38374313d9a9ea22d21658e805600f114a78a2fb935Mark Wei    private void updateActionsInternal() {
384a95161cf364baeea1a9bb098b4f6db961ec8705bAndrew Sapperstein        // If the progress dialog is visible, skip any of the updating
385bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei        if (mActionHandler.isProgressDialogVisible()) {
386a95161cf364baeea1a9bb098b4f6db961ec8705bAndrew Sapperstein            return;
387a95161cf364baeea1a9bb098b4f6db961ec8705bAndrew Sapperstein        }
388a95161cf364baeea1a9bb098b4f6db961ec8705bAndrew Sapperstein
3894aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        // To avoid visibility state transition bugs, every button's visibility should be touched
3904aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        // once by this routine.
391856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei        setButtonVisible(mCancelButton, shouldShowCancel());
392856200a2abc6a90711f6eb99fc0340dd75ef6e9bMark Wei        setButtonVisible(mOverflowButton, shouldShowOverflow());
3934aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
3944aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
395c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei    @Override
396532f48253d23ffcb974ab61856df131021dde02aAndrew Sapperstein    public void onUpdateStatus() {
397c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei        updateSubtitleText();
3984aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
3994aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
400c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei    @Override
4014aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    public void updateProgress(boolean showProgress) {
4024dabcc9f74ea5f75467f6f581d8ef7cd65c2f06ePaul Westbrook        if (mAttachment.isDownloading()) {
403c445aba31c5cc6add9d51296b2c6f5cf89a1e584Andrew Sapperstein            mProgress.setMax(mAttachment.size);
4044aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            mProgress.setProgress(mAttachment.downloadedSize);
4054aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            mProgress.setIndeterminate(!showProgress);
4064aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            mProgress.setVisibility(VISIBLE);
407e18f42d652e171cd4e4bb193482d2e131d91f26eMark Wei            mSubTitle.setVisibility(INVISIBLE);
4084aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        } else {
4094aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein            mProgress.setVisibility(INVISIBLE);
410e18f42d652e171cd4e4bb193482d2e131d91f26eMark Wei            mSubTitle.setVisibility(VISIBLE);
4114aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        }
4124aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
4134aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein
414c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei    private void updateSubtitleText() {
4154aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        // TODO: make this a formatted resource when we have a UX design.
4164aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        // not worth translation right now.
417c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei        final StringBuilder sb = new StringBuilder();
418c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei        if (mAttachment.state == AttachmentState.FAILED) {
419c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei            sb.append(getResources().getString(R.string.download_failed));
420c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei        } else {
421c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei            if (mAttachment.isSavedToExternal()) {
422c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei                sb.append(getResources().getString(R.string.saved, mAttachmentSizeText));
423c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei            } else {
424c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei                sb.append(mAttachmentSizeText);
425c40e5e818876db551e8f7c6f506ebaf38f73ac7aMark Wei            }
426519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon            if (mDisplayType != null) {
427519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                sb.append(' ');
428519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon                sb.append(mDisplayType);
429519c218db6109003ca72a35ffe276ed69b0230a4Martin Hibdon            }
4304aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        }
4314aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein        mSubTitle.setText(sb.toString());
4324aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein    }
4334aa1c1340556c646175c3d0b193be05876ad95a0Andrew Sapperstein}
434