OnePaneController.java revision dd6a7ce32c4003bd0941e2f18fcf5b80b5cd43c5
1a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal/*******************************************************************************
2a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      Copyright (C) 2012 Google Inc.
3a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      Licensed to The Android Open Source Project.
4a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *
5a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      Licensed under the Apache License, Version 2.0 (the "License");
6a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      you may not use this file except in compliance with the License.
7a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      You may obtain a copy of the License at
8a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *
9a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *           http://www.apache.org/licenses/LICENSE-2.0
10a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *
11a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      Unless required by applicable law or agreed to in writing, software
12a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      distributed under the License is distributed on an "AS IS" BASIS,
13a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      See the License for the specific language governing permissions and
15a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *      limitations under the License.
16a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal *******************************************************************************/
17a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal
18a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwalpackage com.android.mail.ui;
19a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal
20d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwalimport android.app.Fragment;
21632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.app.FragmentManager;
22d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwalimport android.app.FragmentTransaction;
231ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huangimport android.app.LoaderManager.LoaderCallbacks;
24559c3b3d302b3f6d2c2cb43a909069d942652e34Mindy Pereiraimport android.net.Uri;
251ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport android.os.Bundle;
26c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sappersteinimport android.text.Html;
27d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwalimport com.android.mail.ConversationListContext;
281ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport com.android.mail.R;
29f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.browse.SecureConversationViewFragment;
30cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwalimport com.android.mail.providers.Account;
319b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereiraimport com.android.mail.providers.Conversation;
323982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereiraimport com.android.mail.providers.Folder;
33fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereiraimport com.android.mail.providers.Settings;
34fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereiraimport com.android.mail.providers.UIProvider;
359e85333dfc57e7c98ffef27cded4712ea598f554Paul Westbrookimport com.android.mail.utils.LogUtils;
36fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira
37a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal/**
38a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal * Controller for one-pane Mail activity. One Pane is used for phones, where screen real estate is
39d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal * limited. This controller also does the layout, since the layout is simpler in the one pane case.
40a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal */
41a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal
42a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal// Called OnePaneActivityController in Gmail.
43a76e5aeff4a54ec70661de35be4f3ecb9d1d2fe2Mindy Pereirapublic final class OnePaneController extends AbstractActivityController {
442bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key used to store {@link #mLastFolderListTransactionId}. */
453982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private static final String FOLDER_LIST_TRANSACTION_KEY = "folder-list-transaction";
462bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key used to store {@link #mLastInboxConversationListTransactionId} */
470e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook    private static final String INBOX_CONVERSATION_LIST_TRANSACTION_KEY =
480e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook            "inbox_conversation-list-transaction";
492bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key used to store {@link #mLastConversationListTransactionId} */
503982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private static final String CONVERSATION_LIST_TRANSACTION_KEY = "conversation-list-transaction";
512bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key used to store {@link #mLastConversationTransactionId}. */
523982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private static final String CONVERSATION_TRANSACTION_KEY = "conversation-transaction";
532bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key used to store {@link #mConversationListVisible}. */
54649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal    private static final String CONVERSATION_LIST_VISIBLE_KEY = "conversation-list-visible";
552bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key used to store {@link #mConversationListNeverShown}. */
56649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal    private static final String CONVERSATION_LIST_NEVER_SHOWN_KEY = "conversation-list-never-shown";
572bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    /** Key to store {@link #mInbox}. */
582bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal    private final static String SAVED_INBOX_KEY = "m-inbox";
592d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook
603982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private static final int INVALID_ID = -1;
612175d0a93263672d4498458c81b404b0999134baVikram Aggarwal    private boolean mConversationListVisible = false;
620e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook    private int mLastInboxConversationListTransactionId = INVALID_ID;
633982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private int mLastConversationListTransactionId = INVALID_ID;
643982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private int mLastConversationTransactionId = INVALID_ID;
653982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private int mLastFolderListTransactionId = INVALID_ID;
663982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private Folder mInbox;
67cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal    /** Whether a conversation list for this account has ever been shown.*/
68cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal    private boolean mConversationListNeverShown = true;
69cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal
70a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal    /**
71a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal     * @param activity
72a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal     * @param viewMode
73a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal     */
74a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal    public OnePaneController(MailActivity activity, ViewMode viewMode) {
75a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal        super(activity, viewMode);
76a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal    }
77a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal
781ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal    @Override
79632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang    public void onRestoreInstanceState(Bundle inState) {
80632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        super.onRestoreInstanceState(inState);
813982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        // TODO(mindyp) handle saved state.
82649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        if (inState == null) {
83649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal            return;
843982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        }
85649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        mLastFolderListTransactionId = inState.getInt(FOLDER_LIST_TRANSACTION_KEY, INVALID_ID);
86649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        mLastInboxConversationListTransactionId =
87649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal                inState.getInt(INBOX_CONVERSATION_LIST_TRANSACTION_KEY, INVALID_ID);
88649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        mLastConversationListTransactionId =
89649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal                inState.getInt(CONVERSATION_LIST_TRANSACTION_KEY, INVALID_ID);
90649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        mLastConversationTransactionId = inState.getInt(CONVERSATION_TRANSACTION_KEY, INVALID_ID);
91649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        mConversationListVisible = inState.getBoolean(CONVERSATION_LIST_VISIBLE_KEY);
92649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        mConversationListNeverShown = inState.getBoolean(CONVERSATION_LIST_NEVER_SHOWN_KEY);
932bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal        mInbox = inState.getParcelable(SAVED_INBOX_KEY);
943982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    }
953982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira
963982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    @Override
973982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    public void onSaveInstanceState(Bundle outState) {
983982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        super.onSaveInstanceState(outState);
993982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        // TODO(mindyp) handle saved state.
1003982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        outState.putInt(FOLDER_LIST_TRANSACTION_KEY, mLastFolderListTransactionId);
1010e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook        outState.putInt(INBOX_CONVERSATION_LIST_TRANSACTION_KEY,
1020e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook                mLastInboxConversationListTransactionId);
1033982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        outState.putInt(CONVERSATION_LIST_TRANSACTION_KEY, mLastConversationListTransactionId);
1043982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        outState.putInt(CONVERSATION_TRANSACTION_KEY, mLastConversationTransactionId);
105649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        outState.putBoolean(CONVERSATION_LIST_VISIBLE_KEY, mConversationListVisible);
106649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal        outState.putBoolean(CONVERSATION_LIST_NEVER_SHOWN_KEY, mConversationListNeverShown);
1072bfb5c0fa1cfe7f25c121d6435dc1a04439f7bacVikram Aggarwal        outState.putParcelable(SAVED_INBOX_KEY, mInbox);
1083982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    }
1093982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira
1103982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    @Override
111d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    public void resetActionBarIcon() {
112d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        final int mode = mViewMode.getMode();
1136343feb48abdf2de6cc9bbc25859e614c0a15f50Vikram Aggarwal        // If the viewmode is not set, preserve existing icon.
1146343feb48abdf2de6cc9bbc25859e614c0a15f50Vikram Aggarwal        if (mode == ViewMode.UNKNOWN) {
1156343feb48abdf2de6cc9bbc25859e614c0a15f50Vikram Aggarwal            return;
1166343feb48abdf2de6cc9bbc25859e614c0a15f50Vikram Aggarwal        }
1172074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        if (!inInbox(mAccount, mConvListContext)
11868f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.SEARCH_RESULTS_LIST
11968f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.SEARCH_RESULTS_CONVERSATION
12068f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.CONVERSATION
12168f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.FOLDER_LIST) {
122d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal            mActionBarView.setBackButton();
123d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        } else {
124d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal            mActionBarView.removeBackButton();
125d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        }
126d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    }
127d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal
1287dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal    /**
1297dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * Returns true if the user is currently in the conversation list view, viewing the default
1307dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * inbox.
1317dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     * @return
1327dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal     */
1332074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal    private static boolean inInbox(final Account account, final ConversationListContext context) {
1342074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        // If we don't have valid state, then we are not in the inbox.
1352074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        if (account == null || context == null || context.folder == null
1362074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal                || account.settings == null) {
1372074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal            return false;
1382074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        }
1392074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        final Uri inboxUri = Settings.getDefaultInboxUri(account.settings);
140ae4ea997d3d3f3c8c11fc5a3e7f9d49f82b4e2e7Vikram Aggarwal        return !ConversationListContext.isSearchResult(context)
141ae4ea997d3d3f3c8c11fc5a3e7f9d49f82b4e2e7Vikram Aggarwal                && context.folder.uri.equals(inboxUri);
1423982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    }
1433982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira
144d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    @Override
145cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal    public void onAccountChanged(Account account) {
146cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal        super.onAccountChanged(account);
147cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal        mConversationListNeverShown = true;
148cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal    }
149cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal
150cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal    @Override
151d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    public boolean onCreate(Bundle savedInstanceState) {
1521ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal        mActivity.setContentView(R.layout.one_pane_activity);
153d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        // The parent class sets the correct viewmode and starts the application off.
154d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        return super.onCreate(savedInstanceState);
1551ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal    }
1561ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal
1571ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal    @Override
1581ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal    protected boolean isConversationListVisible() {
1592175d0a93263672d4498458c81b404b0999134baVikram Aggarwal        return mConversationListVisible;
1601ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal    }
161d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal
162d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    @Override
163d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    public void onViewModeChanged(int newMode) {
164d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        super.onViewModeChanged(newMode);
165632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang
166632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        // When entering conversation list mode, hide and clean up any currently visible
167632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        // conversation.
168632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        // TODO: improve this transition
16949e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal        if (ViewMode.isListMode(newMode)) {
170a3ed834c959ece3453c1b34953fabecb3b19c424Andy Huang            mPagerController.hide(true /* changeVisibility */);
171632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
17249e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal        // When we step away from the conversation mode, we don't have a current conversation
17349e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal        // anymore. Let's blank it out so clients calling getCurrentConversation are not misled.
17449e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal        if (!ViewMode.isConversationMode(newMode)) {
17549e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal            setCurrentConversation(null);
17649e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal        }
177a691fc799aa042fc178d5f194af55b7b63a16a7fVikram Aggarwal        resetActionBarIcon();
178d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    }
179d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal
180d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    @Override
1819b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira    public void showConversationList(ConversationListContext listContext) {
182e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal        super.showConversationList(listContext);
183e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal        enableCabMode();
1843982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        // TODO(viki): Check if the account has been changed since the previous
1853982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        // time.
186ae4ea997d3d3f3c8c11fc5a3e7f9d49f82b4e2e7Vikram Aggarwal        if (ConversationListContext.isSearchResult(listContext)) {
18768f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mViewMode.enterSearchResultsListMode();
18868f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        } else {
18968f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mViewMode.enterConversationListMode();
19068f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        }
1919b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira        // TODO(viki): This account transition looks strange in two pane mode.
1922175d0a93263672d4498458c81b404b0999134baVikram Aggarwal        // Revisit as the app is coming together and improve the look and feel.
193cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal        final int transition = mConversationListNeverShown
194cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal                ? FragmentTransaction.TRANSIT_FRAGMENT_FADE
1959b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira                : FragmentTransaction.TRANSIT_FRAGMENT_OPEN;
19601668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira        Fragment conversationListFragment = ConversationListFragment.newInstance(listContext);
197bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook
1982074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        if (!inInbox(mAccount, mConvListContext)) {
1993982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            // Maintain fragment transaction history so we can get back to the
2003982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            // fragment used to launch this list.
20172a9f3918310f581fecf6411174645ad5b5ae112Mindy Pereira            mLastConversationListTransactionId = replaceFragment(conversationListFragment,
20266150d75d09324e867be42ff8c0ea8fae115ef20Paul Westbrook                    transition, TAG_CONVERSATION_LIST);
2033982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        } else {
2043982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            // If going to the inbox, clear the folder list transaction history.
2053982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            mInbox = listContext.folder;
2060e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook            mLastInboxConversationListTransactionId = replaceFragment(conversationListFragment,
2070e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook                    transition, TAG_CONVERSATION_LIST);
2083982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            mLastFolderListTransactionId = INVALID_ID;
2090e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook
2100e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook            // If we ever to to the inbox, we want to unset the transation id for any other
2110e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook            // non-inbox folder.
2120e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook            mLastConversationListTransactionId = INVALID_ID;
2133982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        }
2142175d0a93263672d4498458c81b404b0999134baVikram Aggarwal        mConversationListVisible = true;
2157dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        onConversationVisibilityChanged(false);
2169f119c72042e4d0382017d5ddcee9aa2113b6425Paul Westbrook        onConversationListVisibilityChanged(true);
217cd09f5e9bf55e6f4310e8dc9408132b9c88e87c3Vikram Aggarwal        mConversationListNeverShown = false;
21828d5f72e0ad0db75b6243ee8125bfe3aadbdcb85Mindy Pereira    }
21928d5f72e0ad0db75b6243ee8125bfe3aadbdcb85Mindy Pereira
22028d5f72e0ad0db75b6243ee8125bfe3aadbdcb85Mindy Pereira    @Override
2211ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    protected void showConversation(Conversation conversation, boolean inLoaderCallbacks) {
2221ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        super.showConversation(conversation, inLoaderCallbacks);
2233d7ca9d2aefd20dc115f20532c1e19fdb60f7d68Vikram Aggarwal        if (conversation == null) {
2241ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            transitionBackToConversationListMode(inLoaderCallbacks);
2253d7ca9d2aefd20dc115f20532c1e19fdb60f7d68Vikram Aggarwal            return;
2263d7ca9d2aefd20dc115f20532c1e19fdb60f7d68Vikram Aggarwal        }
227e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal        disableCabMode();
228ae4ea997d3d3f3c8c11fc5a3e7f9d49f82b4e2e7Vikram Aggarwal        if (ConversationListContext.isSearchResult(mConvListContext)) {
22968f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mViewMode.enterSearchResultsConversationMode();
23068f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        } else {
23168f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mViewMode.enterConversationMode();
23268f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        }
2337dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final FragmentManager fm = mActivity.getFragmentManager();
234f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        final FragmentTransaction ft = fm.beginTransaction();
235f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        ft.addToBackStack(null);
236f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // Switching to conversation view is an incongruous transition:
237f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // we are not replacing a fragment with another fragment as
238f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // usual. Instead, reveal the heretofore inert conversation
239f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // ViewPager and just remove the previously visible fragment
240f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp        // e.g. conversation list, or possibly label list?).
2417dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        final Fragment f = fm.findFragmentById(R.id.content_pane);
242deab11995a1ebb83b24bf567508440088ec943bfPaul Westbrook        // FragmentManager#findFragmentById can return fragments that are not added to the activity.
243deab11995a1ebb83b24bf567508440088ec943bfPaul Westbrook        // We want to make sure that we don't attempt to remove fragments that are not added to the
244deab11995a1ebb83b24bf567508440088ec943bfPaul Westbrook        // activity, as when the transaction is popped off, the FragmentManager will attempt to
245deab11995a1ebb83b24bf567508440088ec943bfPaul Westbrook        // readd the same fragment twice
246deab11995a1ebb83b24bf567508440088ec943bfPaul Westbrook        if (f != null && f.isAdded()) {
2472b703c6c71a369485efc8ade26d449d25669ceecVikram Aggarwal            // TODO: improve this transition
2482b703c6c71a369485efc8ade26d449d25669ceecVikram Aggarwal            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
2492b703c6c71a369485efc8ade26d449d25669ceecVikram Aggarwal            ft.remove(f);
2502b703c6c71a369485efc8ade26d449d25669ceecVikram Aggarwal            ft.commitAllowingStateLoss();
251632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang        }
252a3ed834c959ece3453c1b34953fabecb3b19c424Andy Huang        mPagerController.show(mAccount, mFolder, conversation, true /* changeVisibility */);
2537dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        onConversationVisibilityChanged(true);
2542175d0a93263672d4498458c81b404b0999134baVikram Aggarwal        mConversationListVisible = false;
2559f119c72042e4d0382017d5ddcee9aa2113b6425Paul Westbrook        onConversationListVisibilityChanged(false);
2569b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira    }
2579b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira
2589b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira    @Override
2592d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook    public void showWaitForInitialization() {
2602d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook        super.showWaitForInitialization();
2612d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook
2622d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook        replaceFragment(WaitFragment.newInstance(mAccount),
2636902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal                FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT);
2642d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook    }
2652d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook
266dd6a7ce32c4003bd0941e2f18fcf5b80b5cd43c5Vikram Aggarwal    protected void hideWaitForInitialization() {
2672d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook        transitionToInbox();
2682d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook    }
2692d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook
2702d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook    @Override
2719b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira    public void showFolderList() {
2729e85333dfc57e7c98ffef27cded4712ea598f554Paul Westbrook        if (mAccount == null) {
2739e85333dfc57e7c98ffef27cded4712ea598f554Paul Westbrook            LogUtils.e(LOG_TAG, "Null account in showFolderList");
2749e85333dfc57e7c98ffef27cded4712ea598f554Paul Westbrook            return;
2759e85333dfc57e7c98ffef27cded4712ea598f554Paul Westbrook        }
27611e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira        // Null out the currently selected folder; we have nothing selected the
27711e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira        // first time the user enters the folder list
278c975e8416b64a1ebdec6adee7e65dd1d0928e8d4Mindy Pereira        setHierarchyFolder(null);
27901668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira        mViewMode.enterFolderListMode();
2800ec2a71d1bb48f1fa57f1a4c8a6d81a49f44400fVikram Aggarwal        enableCabMode();
2813982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        mLastFolderListTransactionId = replaceFragment(
2822c0032dd2a4996680ab6e1958fe80a2ebcd01ef3Vikram Aggarwal                FolderListFragment.newInstance(null, mAccount.folderListUri, false),
2836902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal                FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST);
2842175d0a93263672d4498458c81b404b0999134baVikram Aggarwal        mConversationListVisible = false;
2857dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        onConversationVisibilityChanged(false);
2869f119c72042e4d0382017d5ddcee9aa2113b6425Paul Westbrook        onConversationListVisibilityChanged(false);
2879b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira    }
2889b87568c9e9f1c32a9672b315229866a58a1e757Mindy Pereira
2896902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal    /**
2906902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * Replace the content_pane with the fragment specified here. The tag is specified so that
2916902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * the {@link ActivityController} can look up the fragments through the
2926902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * {@link android.app.FragmentManager}.
2936902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * @param fragment
2946902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * @param transition
2956902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * @param tag
2966902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     * @return transaction ID returned when the transition is committed.
2976902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal     */
2982d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook    private int replaceFragment(Fragment fragment, int transition, String tag) {
299d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        FragmentTransaction fragmentTransaction = mActivity.getFragmentManager().beginTransaction();
300d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        fragmentTransaction.addToBackStack(null);
301d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal        fragmentTransaction.setTransition(transition);
3022d50bcdca57756ecad20d21da0d936243215b79cPaul Westbrook        fragmentTransaction.replace(R.id.content_pane, fragment, tag);
3036ffc1b8ad2d600b4886590d68af8f776b3296574Vikram Aggarwal        return fragmentTransaction.commitAllowingStateLoss();
304d7a12cd5b5c2639b653d8c671b04844ef02ee01dVikram Aggarwal    }
30501668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira
3063982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    /**
3073982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * Back works as follows:
3083982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 1) If the user is in the folder list view, go back
3093982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * to the account default inbox.
3103982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 2) If the user is in a conversation list
3113982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * that is not the inbox AND:
3123982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     *  a) they got there by going through the folder
3133982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     *  list view, go back to the folder list view.
3143982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     *  b) they got there by using some other means (account dropdown), go back to the inbox.
3153982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 3) If the user is in a conversation, go back to the conversation list they were last in.
3163982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 4) If the user is in the conversation list for the default account inbox,
3173982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * back exits the app.
3183982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     */
31901668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira    @Override
32001668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira    public boolean onBackPressed() {
3212074a056bb2a634c66996225c55620d2aa6f7ac5Vikram Aggarwal        final int mode = mViewMode.getMode();
3223982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        if (mode == ViewMode.FOLDER_LIST) {
323aea87622d3244be963ee4e9f9780e79b34ffe260Paul Westbrook            final Folder hierarchyFolder = getHierarchyFolder();
324aea87622d3244be963ee4e9f9780e79b34ffe260Paul Westbrook            final FolderListFragment folderListFragment = getFolderListFragment();
325aea87622d3244be963ee4e9f9780e79b34ffe260Paul Westbrook            if (folderListFragment != null &&
326aea87622d3244be963ee4e9f9780e79b34ffe260Paul Westbrook                    folderListFragment.showingHierarchy() && hierarchyFolder != null) {
32711e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                // If we are showing the folder list and the user is exploring
32811e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                // the children of a single parent folder,
32911e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                // back should display the parent folder's parent and siblings.
330ea94550fcca64c3a3510cc10b0e5465d9018668eMindy Pereira                goUpFolderHierarchy(hierarchyFolder);
33111e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira            } else {
332649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal                // We are at the topmost list of folders: go back
33311e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                mLastFolderListTransactionId = INVALID_ID;
33411e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                transitionToInbox();
33511e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira            }
33668f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        } else if (mode == ViewMode.SEARCH_RESULTS_LIST) {
33768f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mActivity.finish();
338b466bcf49502a1178cf7362a81470f3231d8892bMindy Pereira        } else if (mViewMode.isListMode() && !inInbox(mAccount, mConvListContext)) {
33911e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira            if (mLastFolderListTransactionId != INVALID_ID) {
34011e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                // If the user got here by navigating via the folder list, back
34111e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira                // should bring them back to the folder list.
3423982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira                mViewMode.enterFolderListMode();
3433982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira                mActivity.getFragmentManager().popBackStack(mLastFolderListTransactionId, 0);
3443982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            } else {
3453982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira                transitionToInbox();
3463982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            }
34768f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        } else if (mode == ViewMode.CONVERSATION || mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
3481ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            transitionBackToConversationListMode(false /* inLoaderCallbacks */);
3493982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        } else {
3503982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira            mActivity.finish();
3513982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        }
352c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein        mToastBar.hide(false);
3533982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        return true;
3543982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    }
3553982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira
35612a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira    private void goUpFolderHierarchy(Folder current) {
35712a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira        Folder top = current.parent;
35812a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira        if (top != null) {
35999f18d1504203d2f3a82373dcc0937ef0277561aMindy Pereira            setHierarchyFolder(top);
36012a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // Replace this fragment with a new FolderListFragment
36112a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // showing this folder's children if we are not already
36212a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // looking at the child view for this folder.
36312a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            mLastFolderListTransactionId = replaceFragment(FolderListFragment.newInstance(
3642c0032dd2a4996680ab6e1958fe80a2ebcd01ef3Vikram Aggarwal                    top, top.childFoldersListUri, false),
36512a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira                    FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST);
36612a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // Show the up affordance when digging into child folders.
36712a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            mActionBarView.setBackButton();
36812a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira        } else {
36912a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // Otherwise, clear the selected folder and go back to whatever the
37012a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // last folder list displayed was.
37112a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            showFolderList();
37212a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira        }
37312a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira    }
37412a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira
375649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal    /**
376649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal     * Switch to the Inbox by creating a new conversation list context that loads the inbox.
377649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal     */
3783982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private void transitionToInbox() {
3798690e2b71e1a3dd812ce418c9607e21f3a88ab54Mindy Pereira        mViewMode.enterConversationListMode();
380daaf8061dc6fc3cf9f2dda352988c9de08e1a8a8Vikram Aggarwal        if (mInbox == null) {
381ab4863650794e81f35a0fd9abc16a5564d7b102bMindy Pereira            loadAccountInbox();
3823982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        } else {
383daaf8061dc6fc3cf9f2dda352988c9de08e1a8a8Vikram Aggarwal            final ConversationListContext listContext =
384649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal                    ConversationListContext.forFolder(mAccount, mInbox);
385649b9ea3653da73fac0c33c8fb0af18baad12ac3Vikram Aggarwal            // Set the correct context for what the conversation view will be now.
386f6acdade010b2d0f49fd425b33e7f7b376286490Mindy Pereira            onFolderChanged(mInbox);
38772a9f3918310f581fecf6411174645ad5b5ae112Mindy Pereira            showConversationList(listContext);
38801668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira        }
38901668eb393deaf8c8b8abf86be46109614a98631Mindy Pereira    }
390f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira
391118b3f6443f1859ff4866c97c0e8896f3415f730Mindy Pereira    @Override
392505df5f59c92adbe8eaa734321c1d3f91be84a4aMindy Pereira    public void onFolderSelected(Folder folder) {
393a1f99981919755e50f31fe300517d2fed752997eMindy Pereira        if (folder.hasChildren && !folder.equals(getHierarchyFolder())) {
3940f7ae7a2d244463f75b3d4e1f79e27305a4dcb38Mindy Pereira            mViewMode.enterFolderListMode();
395c975e8416b64a1ebdec6adee7e65dd1d0928e8d4Mindy Pereira            setHierarchyFolder(folder);
39656e3f50f5aee6606035eae4b713ef634c4f3a686Mindy Pereira            // Replace this fragment with a new FolderListFragment
39711e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira            // showing this folder's children if we are not already
39811e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira            // looking at the child view for this folder.
39956e3f50f5aee6606035eae4b713ef634c4f3a686Mindy Pereira            mLastFolderListTransactionId = replaceFragment(
4002c0032dd2a4996680ab6e1958fe80a2ebcd01ef3Vikram Aggarwal                    FolderListFragment.newInstance(folder, folder.childFoldersListUri, false),
4016902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal                    FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST);
40212a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            // Show the up affordance when digging into child folders.
40312a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            mActionBarView.setBackButton();
40411e3596e8c5978d07195ae2d7c8a96bb51aa75b3Mindy Pereira        } else {
40512a4d8040d64501aa5a24c25865c806331560b74Mindy Pereira            super.onFolderSelected(folder);
406118b3f6443f1859ff4866c97c0e8896f3415f730Mindy Pereira        }
407118b3f6443f1859ff4866c97c0e8896f3415f730Mindy Pereira    }
408118b3f6443f1859ff4866c97c0e8896f3415f730Mindy Pereira
4093982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    private boolean isTransactionIdValid(int id) {
4103982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira        return id >= 0;
4113982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    }
4123982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira
4133982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira    /**
4143982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * Up works as follows:
4153982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 1) If the user is in a conversation list that is not the default account inbox,
4163982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * a conversation, or the folder list, up follows the rules of back.
4173982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 2) If the user is in search results, up exits search
4183982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * mode and returns the user to whatever view they were in when they began search.
4193982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     * 3) If the user is in the inbox, there is no up.
4203982e236fb2dd36d460df4dbf24e07e8ba55b3bdMindy Pereira     */
421f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira    @Override
422f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira    public boolean onUpPressed() {
4239da85df06175d25c52a09e08df3b02d1fd9cc6b7Vikram Aggarwal        final int mode = mViewMode.getMode();
42468f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        if (mode == ViewMode.SEARCH_RESULTS_LIST) {
42568f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mActivity.finish();
426b466bcf49502a1178cf7362a81470f3231d8892bMindy Pereira        } else if ((!inInbox(mAccount, mConvListContext) && mViewMode.isListMode())
42768f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.CONVERSATION
42868f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.FOLDER_LIST
42968f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira                || mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
430f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira            // Same as go back.
431f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira            mActivity.onBackPressed();
432f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira        }
433f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira        return true;
434f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira    }
435f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira
4361ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    private void transitionBackToConversationListMode(boolean inLoaderCallbacks) {
4379da85df06175d25c52a09e08df3b02d1fd9cc6b7Vikram Aggarwal        final int mode = mViewMode.getMode();
43890d89e2194cecb6ff0179c8159870575edf7365eVikram Aggarwal        enableCabMode();
43968f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        if (mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
44068f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mViewMode.enterSearchResultsListMode();
44168f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        } else {
44268f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira            mViewMode.enterConversationListMode();
44368f2e222b4ffccd9f67f02b3a9cfdb3841a7eb43Mindy Pereira        }
44421ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira        if (isTransactionIdValid(mLastConversationListTransactionId)) {
4451ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            safelyPopBackStack(mLastConversationListTransactionId, inLoaderCallbacks);
4460e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook        } else if (isTransactionIdValid(mLastInboxConversationListTransactionId)) {
4471ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            safelyPopBackStack(mLastInboxConversationListTransactionId, inLoaderCallbacks);
4480e3fd9d61bc18ad9f828bb3c4dd24fc851f11df5Paul Westbrook            onFolderChanged(mInbox);
44921ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira        } else {
4509da85df06175d25c52a09e08df3b02d1fd9cc6b7Vikram Aggarwal            // TODO: revisit if this block is necessary
45153d46a3e3b3c3d97696ecfffc3a99ac9250063e8Vikram Aggarwal            final ConversationListContext listContext = ConversationListContext.forFolder(
45221ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira                    mAccount, mInbox);
45321ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira            // Set the correct context for what the conversation view will be now.
45421ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira            onFolderChanged(mInbox);
45521ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira            showConversationList(listContext);
45621ab490d4919985d611bc36ae2d8aea86a911499Mindy Pereira        }
4579f119c72042e4d0382017d5ddcee9aa2113b6425Paul Westbrook        mConversationListVisible = true;
4587dd054e39986de84a213c56a3c11ac94731402e6Vikram Aggarwal        onConversationVisibilityChanged(false);
4599f119c72042e4d0382017d5ddcee9aa2113b6425Paul Westbrook        onConversationListVisibilityChanged(true);
460f5acda4a4b7c9e8ecacb41cb7d570ef426b6d4fcMindy Pereira    }
461b849dfbda3c917f078a5c09f03906886c27ecbecMindy Pereira
4621ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    /**
4631ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * Pop to a specified point in the fragment back stack without causing IllegalStateExceptions
4641ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * from committing a fragment transaction "at the wrong time".
4651ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * <p>
4661ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * If the caller specifies that we are in
4671ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * the scope of an {@link LoaderCallbacks#onLoadFinished(android.content.Loader, Object)},
4681ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * this method will pop back in a Handler. The deferred job will also check that the Activity
4691ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * is in a valid state for fragment transactions, using {@link #safeToModifyFragments()}.
4701ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * Otherwise, this method will pop back immediately if safe. Finally, if we are not in
4711ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * onLoadFinished and it's not safe, this method will just ignore the request.
4721ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     *
4731ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * @param transactionId back stack destination to pop to
4741ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * @param inLoaderCallbacks whether we are in the scope of an onLoadFinished (when fragment
4751ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     * transactions are disallowed)
4761ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang     */
4771ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    private void safelyPopBackStack(int transactionId, boolean inLoaderCallbacks) {
4781ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        final PopBackStackRunnable r = new PopBackStackRunnable(transactionId);
4791ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        if (inLoaderCallbacks) {
4801ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            // always run deferred. ensure deferred job checks safety.
4811ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            mHandler.post(r);
4821ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        } else if (safeToModifyFragments()) {
4831ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            // run now
4841ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            r.popBackStack();
4851ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        } else {
4861ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            // ignore
4871ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            LogUtils.i(LOG_TAG, "Activity has been saved; ignoring unsafe immediate request"
4881ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                    + " to pop back stack");
4891ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
4901ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    }
4911ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
492b849dfbda3c917f078a5c09f03906886c27ecbecMindy Pereira    @Override
493b849dfbda3c917f078a5c09f03906886c27ecbecMindy Pereira    public boolean shouldShowFirstConversation() {
494b849dfbda3c917f078a5c09f03906886c27ecbecMindy Pereira        return false;
495b849dfbda3c917f078a5c09f03906886c27ecbecMindy Pereira    }
496fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira
497fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira    @Override
498d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira    public void onUndoAvailable(ToastBarOperation op) {
4990963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira        if (op != null && mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO)) {
5007f602f7a64f176894ccb7942a6642f22584c3894Vikram Aggarwal            final int mode = mViewMode.getMode();
501dbab8fab0c98dc2d56bbe17c7436719129952b7bMindy Pereira            final ConversationListFragment convList = getConversationListFragment();
5020963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira            switch (mode) {
503b466bcf49502a1178cf7362a81470f3231d8892bMindy Pereira                case ViewMode.SEARCH_RESULTS_CONVERSATION:
5040963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira                case ViewMode.CONVERSATION:
505c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                    mToastBar.setConversationMode(true);
506c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                    mToastBar.show(
507c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                            getUndoClickedListener(
508c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                                    convList != null ? convList.getAnimatedAdapter() : null),
509c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                            0,
51001f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira                            Html.fromHtml(op.getDescription(mActivity.getActivityContext(),
51101f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira                                    mFolder)),
512c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                            true, /* showActionIcon */
513c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                            R.string.undo,
514d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira                            true,  /* replaceVisibleToast */
515d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira                            op);
5160963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira                    break;
517b466bcf49502a1178cf7362a81470f3231d8892bMindy Pereira                case ViewMode.SEARCH_RESULTS_LIST:
5180963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira                case ViewMode.CONVERSATION_LIST:
5196902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal                    if (convList != null) {
520c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                        mToastBar.setConversationMode(false);
521c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                        mToastBar.show(
522c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                                getUndoClickedListener(convList.getAnimatedAdapter()),
523c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                                0,
52401f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira                                Html.fromHtml(op.getDescription(mActivity.getActivityContext(),
52501f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira                                        mFolder)),
526c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                                true, /* showActionIcon */
527c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                                R.string.undo,
528d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira                                true,  /* replaceVisibleToast */
529d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira                                op);
5304765c5c90802d0abcf2b05c4967e7dd7d2284f9aMindy Pereira                    } else {
5314765c5c90802d0abcf2b05c4967e7dd7d2284f9aMindy Pereira                        mActivity.setPendingToastOperation(op);
5326902dcf8688d7d0691639f49365a78a3a78fe9e3Vikram Aggarwal                    }
5330963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira                    break;
5340963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira            }
5350963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira        }
5360963ef8394e1f0bca3f931f930b127b00790361aMindy Pereira    }
537c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein
538c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein    @Override
5399d7519d18e8ddbcdd59b37eec7c85210fca0e8c2Andrew Sapperstein    public void onError(final Folder folder, boolean replaceVisibleToast) {
540c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein        final int mode = mViewMode.getMode();
541c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein        switch (mode) {
542c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein            case ViewMode.SEARCH_RESULTS_LIST:
543c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein            case ViewMode.CONVERSATION_LIST:
5449d7519d18e8ddbcdd59b37eec7c85210fca0e8c2Andrew Sapperstein                showErrorToast(folder, replaceVisibleToast);
545c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                break;
546c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein            default:
547c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein                break;
548c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein        }
549c2c9dc14aa184db1f05b8c060b27d97dda5a3ca4Andrew Sapperstein    }
55030745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook
55130745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook    @Override
55230745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook    public String getHelpContext() {
55330745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook        final int mode = mViewMode.getMode();
55430745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook        switch (mode) {
55530745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook            case ViewMode.FOLDER_LIST:
55630745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook                return mContext.getString(R.string.one_pane_folder_list_help_context);
55730745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook        }
55830745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook        return super.getHelpContext();
55930745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook    }
5601ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
5611ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    private final class PopBackStackRunnable implements Runnable {
5621ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
5631ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        private final int mTransactionId;
5641ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
5651ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        public PopBackStackRunnable(int transactionId) {
5661ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            mTransactionId = transactionId;
5671ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
5681ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
5691ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        public void popBackStack() {
5701ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            mActivity.getFragmentManager().popBackStack(mTransactionId, 0);
5711ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
5721ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
5731ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        @Override
5741ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        public void run() {
5751ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            if (safeToModifyFragments()) {
5761ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                popBackStack();
5771ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            } else {
5781ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                LogUtils.i(LOG_TAG, "Activity has been saved; ignoring unsafe deferred request"
5791ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang                        + " to pop back stack");
5801ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang            }
5811ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang        }
5821ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang    }
5831ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang
584a55b36cb6b75ce8096812183651e89115300975aVikram Aggarwal}
585