1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Copyright (C) 2011 The Android Open Source Project
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License");
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * you may not use this file except in compliance with the License.
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * You may obtain a copy of the License at
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage com.android.email.activity;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.app.Activity;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.app.Fragment;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.app.FragmentManager;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.app.FragmentTransaction;
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.os.Bundle;
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.util.Log;
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.Menu;
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.MenuInflater;
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.MenuItem;
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.Email;
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.FolderProperties;
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.MessageListContext;
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.Preferences;
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.R;
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.RefreshManager;
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.RequireManualSyncDialog;
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.activity.setup.AccountSettings;
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.activity.setup.MailboxSettings;
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.Logging;
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.Account;
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent.Message;
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.HostAuth;
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.Mailbox;
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.utility.EmailAsyncTask;
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.utility.Utility;
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.google.common.base.Objects;
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.google.common.base.Preconditions;
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.LinkedList;
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.List;
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Base class for the UI controller.
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookabstract class UIControllerBase implements MailboxListFragment.Callback,
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageListFragment.Callback, MessageViewFragment.Callback  {
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static final boolean DEBUG_FRAGMENTS = false; // DO NOT SUBMIT WITH TRUE
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static final String KEY_LIST_CONTEXT = "UIControllerBase.listContext";
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** The owner activity */
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    final EmailActivity mActivity;
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    final FragmentManager mFragmentManager;
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final ActionBarController mActionBarController;
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private MessageOrderManager mOrderManager;
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final MessageOrderManagerCallback mMessageOrderManagerCallback =
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            new MessageOrderManagerCallback();
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    final RefreshManager mRefreshManager;
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Fragments that are installed.
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * A fragment is installed in {@link Fragment#onActivityCreated} and uninstalled in
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link Fragment#onDestroyView}, using {@link FragmentInstallable} callbacks.
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This means fragments in the back stack are *not* installed.
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * We set callbacks to fragments only when they are installed.
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @see FragmentInstallable
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private MailboxListFragment mMailboxListFragment;
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private MessageListFragment mMessageListFragment;
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private MessageViewFragment mMessageViewFragment;
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * To avoid double-deleting a fragment (which will cause a runtime exception),
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * we put a fragment in this list when we {@link FragmentTransaction#remove(Fragment)} it,
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * and remove from the list when we actually uninstall it.
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final List<Fragment> mRemovedFragments = new LinkedList<Fragment>();
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The NfcHandler implements Near Field Communication sharing features
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * whenever the activity is in the foreground.
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private NfcHandler mNfcHandler;
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The active context for the current MessageList.
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * In some UI layouts such as the one-pane view, the message list may not be visible, but is
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * on the backstack. This list context will still be accessible in those cases.
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Should be set using {@link #setListContext(MessageListContext)}.
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected MessageListContext mListContext;
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private class RefreshListener implements RefreshManager.Listener {
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private MenuItem mRefreshIcon;
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public void onMessagingError(final long accountId, long mailboxId, final String message) {
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            updateRefreshIcon();
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public void onRefreshStatusChanged(long accountId, long mailboxId) {
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            updateRefreshIcon();
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        void setRefreshIcon(MenuItem icon) {
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mRefreshIcon = icon;
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            updateRefreshIcon();
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private void updateRefreshIcon() {
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (mRefreshIcon == null) {
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return;
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (isRefreshInProgress()) {
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mRefreshIcon.setActionView(R.layout.action_bar_indeterminate_progress);
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mRefreshIcon.setActionView(null);
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    };
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final RefreshListener mRefreshListener = new RefreshListener();
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public UIControllerBase(EmailActivity activity) {
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActivity = activity;
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mFragmentManager = activity.getFragmentManager();
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mRefreshManager = RefreshManager.getInstance(mActivity);
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActionBarController = createActionBarController(activity);
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (DEBUG_FRAGMENTS) {
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            FragmentManager.enableDebugLogging(true);
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Called by the base class to let a subclass create an {@link ActionBarController}.
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract ActionBarController createActionBarController(Activity activity);
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return the layout ID for the activity. */
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public abstract int getLayoutId();
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Must be called just after the activity sets up the content view.  Used to initialize views.
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * (Due to the complexity regarding class/activity initialization order, we can't do this in
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the constructor.)
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityViewReady() {
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityViewReady");
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Called at the end of {@link EmailActivity#onCreate}.
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityCreated() {
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityCreated");
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mRefreshManager.registerListener(mRefreshListener);
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActionBarController.onActivityCreated();
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mNfcHandler = NfcHandler.register(this, mActivity);
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onStart} callback.
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityStart() {
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityStart");
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isMessageViewInstalled()) {
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            updateMessageOrderManager();
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onResume} callback.
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityResume() {
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityResume");
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        refreshActionBar();
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mNfcHandler != null) {
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mNfcHandler.onAccountChanged();  // workaround for email not set on initial load
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        long accountId = getUIAccountId();
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Preferences.getPreferences(mActivity).setLastUsedAccountId(accountId);
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        showAccountSpecificWarning(accountId);
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onPause} callback.
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityPause() {
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityPause");
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onStop} callback.
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityStop() {
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityStop");
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        stopMessageOrderManager();
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onDestroy} callback.
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onActivityDestroy() {
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onActivityDestroy");
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActionBarController.onActivityDestroy();
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mRefreshManager.unregisterListener(mRefreshListener);
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mTaskTracker.cancellAllInterrupt();
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onSaveInstanceState} callback.
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onSaveInstanceState(Bundle outState) {
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onSaveInstanceState");
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActionBarController.onSaveInstanceState(outState);
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        outState.putParcelable(KEY_LIST_CONTEXT, mListContext);
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onRestoreInstanceState} callback.
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
260bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onRestoreInstanceState(Bundle savedInstanceState) {
261bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
262bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " restoreInstanceState");
263bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
264bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActionBarController.onRestoreInstanceState(savedInstanceState);
265bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mListContext = savedInstanceState.getParcelable(KEY_LIST_CONTEXT);
266bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
267bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
268bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // MessageViewFragment$Callback
269bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
270bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onMessageSetUnread() {
271bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        doAutoAdvance();
272bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
273bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
274bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // MessageViewFragment$Callback
275bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
276bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onMessageNotExists() {
277bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        doAutoAdvance();
278bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
279bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
280bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // MessageViewFragment$Callback
281bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
282bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onRespondedToInvite(int response) {
283bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        doAutoAdvance();
284bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
285bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
286bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // MessageViewFragment$Callback
287bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
288bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onBeforeMessageGone() {
289bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        doAutoAdvance();
290bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
291bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
292bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
293bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Install a fragment.  Must be caleld from the host activity's
294bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link FragmentInstallable#onInstallFragment}.
295bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
296bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final void onInstallFragment(Fragment fragment) {
297bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
298bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onInstallFragment  fragment=" + fragment);
299bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
300bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (fragment instanceof MailboxListFragment) {
301bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            installMailboxListFragment((MailboxListFragment) fragment);
302bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else if (fragment instanceof MessageListFragment) {
303bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            installMessageListFragment((MessageListFragment) fragment);
304bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else if (fragment instanceof MessageViewFragment) {
305bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            installMessageViewFragment((MessageViewFragment) fragment);
306bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
307bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IllegalArgumentException("Tried to install unknown fragment");
308bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
309bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
310bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
311bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Install fragment */
312bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void installMailboxListFragment(MailboxListFragment fragment) {
313bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMailboxListFragment = fragment;
314bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMailboxListFragment.setCallback(this);
315bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
316bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // TODO: consolidate this refresh with the one that the Fragment itself does. since
317bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // the fragment calls setHasOptionsMenu(true) - it invalidates when it gets attached.
318bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // However the timing is slightly different and leads to a delay in update if this isn't
319bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // here - investigate why. same for the other installs.
320bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        refreshActionBar();
321bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
322bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
323bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Install fragment */
324bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void installMessageListFragment(MessageListFragment fragment) {
325bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageListFragment = fragment;
326bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageListFragment.setCallback(this);
327bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        refreshActionBar();
328bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
329bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
330bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Install fragment */
331bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void installMessageViewFragment(MessageViewFragment fragment) {
332bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageViewFragment = fragment;
333bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageViewFragment.setCallback(this);
334bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
335bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        updateMessageOrderManager();
336bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        refreshActionBar();
337bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
338bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
339bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
340bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Uninstall a fragment.  Must be caleld from the host activity's
341bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link FragmentInstallable#onUninstallFragment}.
342bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
343bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final void onUninstallFragment(Fragment fragment) {
344bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
345bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " onUninstallFragment  fragment=" + fragment);
346bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
347bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mRemovedFragments.remove(fragment);
348bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (fragment == mMailboxListFragment) {
349bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            uninstallMailboxListFragment();
350bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else if (fragment == mMessageListFragment) {
351bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            uninstallMessageListFragment();
352bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else if (fragment == mMessageViewFragment) {
353bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            uninstallMessageViewFragment();
354bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
355bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IllegalArgumentException("Tried to uninstall unknown fragment");
356bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
357bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
358bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
359bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Uninstall {@link MailboxListFragment} */
360bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void uninstallMailboxListFragment() {
361bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMailboxListFragment.setCallback(null);
362bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMailboxListFragment = null;
363bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
364bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
365bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Uninstall {@link MessageListFragment} */
366bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void uninstallMessageListFragment() {
367bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageListFragment.setCallback(null);
368bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageListFragment = null;
369bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
370bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
371bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Uninstall {@link MessageViewFragment} */
372bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void uninstallMessageViewFragment() {
373bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageViewFragment.setCallback(null);
374bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mMessageViewFragment = null;
375bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
376bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
377bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
378bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * If a {@link Fragment} is not already in {@link #mRemovedFragments},
379bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link FragmentTransaction#remove} it and add to the list.
380bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
381bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Do nothing if {@code fragment} is null.
382bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
383bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final void removeFragment(FragmentTransaction ft, Fragment fragment) {
384bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
385bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " removeFragment fragment=" + fragment);
386bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
387bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (fragment == null) {
388bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
389bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
390bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!mRemovedFragments.contains(fragment)) {
391bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Remove try/catch when b/4981556 is fixed (framework bug)
392bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            try {
393bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ft.remove(fragment);
394bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } catch (IllegalStateException ex) {
395bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Log.e(Logging.LOG_TAG, "Swalling IllegalStateException due to known bug for "
396bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        + " fragment: " + fragment, ex);
397bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Log.e(Logging.LOG_TAG, Utility.dumpFragment(fragment));
398bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
399bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            addFragmentToRemovalList(fragment);
400bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
401bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
402bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
403bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
404bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Remove a {@link Fragment} from {@link #mRemovedFragments}.  No-op if {@code fragment} is
405bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * null.
406bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
407bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link #removeMailboxListFragment}, {@link #removeMessageListFragment} and
408bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link #removeMessageViewFragment} all call this, so subclasses don't have to do this when
409bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * using them.
410bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
411bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * However, unfortunately, subclasses have to call this manually when popping from the
412bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * back stack to avoid double-delete.
413bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
414bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void addFragmentToRemovalList(Fragment fragment) {
415bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (fragment != null) {
416bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mRemovedFragments.add(fragment);
417bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
418bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
419bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
420bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
421bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Remove the fragment if it's installed.
422bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
423bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected FragmentTransaction removeMailboxListFragment(FragmentTransaction ft) {
424bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        removeFragment(ft, mMailboxListFragment);
425bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return ft;
426bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
427bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
428bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
429bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Remove the fragment if it's installed.
430bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
431bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected FragmentTransaction removeMessageListFragment(FragmentTransaction ft) {
432bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        removeFragment(ft, mMessageListFragment);
433bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return ft;
434bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
435bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
436bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
437bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Remove the fragment if it's installed.
438bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
439bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected FragmentTransaction removeMessageViewFragment(FragmentTransaction ft) {
440bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        removeFragment(ft, mMessageViewFragment);
441bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return ft;
442bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
443bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
444bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return true if a {@link MailboxListFragment} is installed. */
445bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final boolean isMailboxListInstalled() {
446bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mMailboxListFragment != null;
447bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
448bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
449bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return true if a {@link MessageListFragment} is installed. */
450bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final boolean isMessageListInstalled() {
451bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mMessageListFragment != null;
452bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
453bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
454bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return true if a {@link MessageViewFragment} is installed. */
455bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final boolean isMessageViewInstalled() {
456bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mMessageViewFragment != null;
457bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
458bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
459bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return the installed {@link MailboxListFragment} or null. */
460bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final MailboxListFragment getMailboxListFragment() {
461bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mMailboxListFragment;
462bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
463bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
464bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return the installed {@link MessageListFragment} or null. */
465bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final MessageListFragment getMessageListFragment() {
466bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mMessageListFragment;
467bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
468bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
469bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** @return the installed {@link MessageViewFragment} or null. */
470bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final MessageViewFragment getMessageViewFragment() {
471bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mMessageViewFragment;
472bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
473bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
474bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
475bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Commit a {@link FragmentTransaction}.
476bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
477bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void commitFragmentTransaction(FragmentTransaction ft) {
478bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (DEBUG_FRAGMENTS) {
479bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, this + " commitFragmentTransaction: " + ft);
480bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
481bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!ft.isEmpty()) {
482bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // NB: there should be no cases in which a transaction is committed after
483bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // onSaveInstanceState. Unfortunately, the "state loss" check also happens when in
484bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // LoaderCallbacks.onLoadFinished, and we wish to perform transactions there. The check
485bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // by the framework is conservative and prevents cases where there are transactions
486bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // affecting Loader lifecycles - but we have no such cases.
487bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // TODO: use asynchronous callbacks from loaders to avoid this implicit dependency
488bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            ft.commitAllowingStateLoss();
489bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mFragmentManager.executePendingTransactions();
490bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
491bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
492bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
493bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
494bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the currently selected account ID, *or* {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
495bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
496bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @see #getActualAccountId()
497bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
498bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public abstract long getUIAccountId();
499bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
500bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
501bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return true if an account is selected, or the current view is the combined view.
502bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
503bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final boolean isAccountSelected() {
504bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getUIAccountId() != Account.NO_ACCOUNT;
505bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
506bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
507bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
508bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return if an actual account is selected.  (i.e. {@link Account#ACCOUNT_ID_COMBINED_VIEW}
509bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * is not considered "actual".s)
510bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
511bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final boolean isActualAccountSelected() {
512bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isAccountSelected() && (getUIAccountId() != Account.ACCOUNT_ID_COMBINED_VIEW);
513bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
514bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
515bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
516bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the currently selected account ID.  If the current view is the combined view,
517bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * it'll return {@link Account#NO_ACCOUNT}.
518bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
519bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @see #getUIAccountId()
520bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
521bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final long getActualAccountId() {
522bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isActualAccountSelected() ? getUIAccountId() : Account.NO_ACCOUNT;
523bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
524bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
525bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
526bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Show the default view for the given account.
527bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
528bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param accountId ID of the account to load.  Can be {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
529bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *     Must never be {@link Account#NO_ACCOUNT}.
530bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param forceShowInbox If {@code false} and the given account is already selected, do nothing.
531bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *        If {@code false}, we always change the view even if the account is selected.
532bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
533bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final void switchAccount(long accountId, boolean forceShowInbox) {
534bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
535bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Account.isSecurityHold(mActivity, accountId)) {
536bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            ActivityHelper.showSecurityHoldDialog(mActivity, accountId);
537bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActivity.finish();
538bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
539bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
540bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
541bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (accountId == getUIAccountId() && !forceShowInbox) {
542bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Do nothing if the account is already selected.  Not even going back to the inbox.
543bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
544bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
545bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
546bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            openMailbox(accountId, Mailbox.QUERY_ALL_INBOXES);
547bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
548bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            long inboxId = Mailbox.findMailboxOfType(mActivity, accountId, Mailbox.TYPE_INBOX);
549bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (inboxId == Mailbox.NO_MAILBOX) {
550bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // The account doesn't have Inbox yet... Redirect to Welcome and let it wait for
551bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // the initial sync...
552bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Log.w(Logging.LOG_TAG, "Account " + accountId +" doesn't have Inbox.  Redirecting"
553bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        + " to Welcome...");
554bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Welcome.actionOpenAccountInbox(mActivity, accountId);
555bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mActivity.finish();
556bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
557bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                openMailbox(accountId, inboxId);
558bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
559bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
560bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mNfcHandler != null) {
561bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mNfcHandler.onAccountChanged();
562bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
563bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Preferences.getPreferences(mActivity).setLastUsedAccountId(accountId);
564bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        showAccountSpecificWarning(accountId);
565bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
566bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
567bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
568bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns the id of the parent mailbox used for the mailbox list fragment.
569bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
570bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * IMPORTANT: Do not confuse {@link #getMailboxListMailboxId()} with
571bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *     {@link #getMessageListMailboxId()}
572bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
573bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected long getMailboxListMailboxId() {
574bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isMailboxListInstalled() ? getMailboxListFragment().getSelectedMailboxId()
575bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                : Mailbox.NO_MAILBOX;
576bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
577bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
578bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
579bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns the id of the mailbox used for the message list fragment.
580bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
581bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * IMPORTANT: Do not confuse {@link #getMailboxListMailboxId()} with
582bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *     {@link #getMessageListMailboxId()}
583bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
584bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected long getMessageListMailboxId() {
585bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isMessageListInstalled() ? getMessageListFragment().getMailboxId()
586bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                : Mailbox.NO_MAILBOX;
587bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
588bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
589bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
590bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Shortcut for {@link #open} with {@link Message#NO_MESSAGE}.
591bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
592bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final void openMailbox(long accountId, long mailboxId) {
593bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        open(MessageListContext.forMailbox(accountId, mailboxId), Message.NO_MESSAGE);
594bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
595bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
596bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
597bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Opens a given list
598bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param listContext the list context for the message list to open
599bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param messageId if specified and not {@link Message#NO_MESSAGE}, will open the message
600bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *     in the message list.
601bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
602bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public final void open(final MessageListContext listContext, final long messageId) {
603bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        setListContext(listContext);
604bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        openInternal(listContext, messageId);
605bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
606bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (listContext.isSearch()) {
607bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActionBarController.enterSearchMode(listContext.getSearchParams().mFilter);
608bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
609bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
610bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
611bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
612bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Sets the internal value of the list context for the message list.
613bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
614bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void setListContext(MessageListContext listContext) {
615bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Objects.equal(listContext, mListContext)) {
616bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
617bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
618bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
619bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Email.DEBUG && Logging.DEBUG_LIFECYCLE) {
620bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.i(Logging.LOG_TAG, this + " setListContext: " + listContext);
621bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
622bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mListContext = listContext;
623bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
624bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
625bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract void openInternal(
626bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final MessageListContext listContext, final long messageId);
627bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
628bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
629bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Performs the back action.
630bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
631bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param isSystemBackKey <code>true</code> if the system back key was pressed.
632bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>false</code> if it's caused by the "home" icon click on the action bar.
633bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
634bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public abstract boolean onBackPressed(boolean isSystemBackKey);
635bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
636bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onSearchStarted() {
637bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Show/hide the original search icon.
638bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActivity.invalidateOptionsMenu();
639bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
640bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
641bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
642bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Must be called from {@link Activity#onSearchRequested()}.
643bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This initiates the search entry mode - see {@link #onSearchSubmit} for when the search
644bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * is actually submitted.
645bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
646bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onSearchRequested() {
647bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        long accountId = getActualAccountId();
648bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean accountSearchable = false;
649bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (accountId > 0) {
650bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Account account = Account.restoreAccountWithId(mActivity, accountId);
651bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (account != null) {
652bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                String protocol = account.getProtocol(mActivity);
653bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                accountSearchable = (account.mFlags & Account.FLAGS_SUPPORTS_SEARCH) != 0;
654bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
655bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
656bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
657bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!accountSearchable) {
658bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
659bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
660bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
661bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isMessageListReady()) {
662bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActionBarController.enterSearchMode(null);
663bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
664bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
665bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
666bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
667bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return Whether or not a message list is ready and has its initial meta data loaded.
668bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
669bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected boolean isMessageListReady() {
670bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isMessageListInstalled() && getMessageListFragment().hasDataLoaded();
671bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
672bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
673bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
674bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Determines the mailbox to search, if a search was to be initiated now.
675bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This will return {@code null} if the UI is not focused on any particular mailbox to search
676bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * on.
677bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
678bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private Mailbox getSearchableMailbox() {
679bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!isMessageListReady()) {
680bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return null;
681bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
682bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageListFragment messageList = getMessageListFragment();
683bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
684bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // If already in a search, future searches will search the original mailbox.
685bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mListContext.isSearch()
686bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ? messageList.getSearchedMailbox()
687bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                : messageList.getMailbox();
688bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
689bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
690bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // TODO: this logic probably needs to be tested in the backends as well, so it may be nice
691bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // to consolidate this to a centralized place, so that they don't get out of sync.
692bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
693bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return whether or not this account should do a global search instead when a user
694bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *     initiates a search on the given mailbox.
695bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
696bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static boolean shouldDoGlobalSearch(Account account, Mailbox mailbox) {
697bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return ((account.mFlags & Account.FLAGS_SUPPORTS_GLOBAL_SEARCH) != 0)
698bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                && (mailbox.mType == Mailbox.TYPE_INBOX);
699bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
700bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
701bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
702bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Retrieves the hint text to be shown for when a search entry is being made.
703bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
704bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected String getSearchHint() {
705bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!isMessageListReady()) {
706bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return "";
707bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
708bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Account account = getMessageListFragment().getAccount();
709bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Mailbox mailbox = getSearchableMailbox();
710bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
711bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mailbox == null) {
712bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return "";
713bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
714bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
715bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (shouldDoGlobalSearch(account, mailbox)) {
716bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return mActivity.getString(R.string.search_hint);
717bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
718bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
719bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Regular mailbox, or IMAP - search within that mailbox.
720bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        String mailboxName = FolderProperties.getInstance(mActivity).getDisplayName(mailbox);
721bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return String.format(
722bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mActivity.getString(R.string.search_mailbox_hint),
723bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mailboxName);
724bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
725bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
726bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
727bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Kicks off a search query, if the UI is in a state where a search is possible.
728bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
729bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void onSearchSubmit(final String queryTerm) {
730bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final long accountId = getUIAccountId();
731bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!Account.isNormalAccount(accountId)) {
732bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return; // Invalid account to search from.
733bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
734bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
735bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Mailbox searchableMailbox = getSearchableMailbox();
736bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (searchableMailbox == null) {
737bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
738bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
739bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final long mailboxId = searchableMailbox.mId;
740bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
741bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Email.DEBUG) {
742bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG,
743bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    "Submitting search: [" + queryTerm + "] in mailboxId=" + mailboxId);
744bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
745bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
746bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActivity.startActivity(EmailActivity.createSearchIntent(
747bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mActivity, accountId, mailboxId, queryTerm));
748bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
749bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
750bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // TODO: this causes a slight flicker.
751bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // A new instance of the activity will sit on top. When the user exits search and
752bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // returns to this activity, the search box should not be open then.
753bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActionBarController.exitSearchMode();
754bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
755bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
756bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
757bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles exiting of search entry mode.
758bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
759bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void onSearchExit() {
760bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if ((mListContext != null) && mListContext.isSearch()) {
761bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActivity.finish();
762bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
763bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Re show the search icon.
764bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActivity.invalidateOptionsMenu();
765bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
766bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
767bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
768bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
769bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onCreateOptionsMenu} callback.
770bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
771bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) {
772bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        inflater.inflate(R.menu.email_activity_options, menu);
773bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return true;
774bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
775bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
776bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
777bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onPrepareOptionsMenu} callback.
778bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
779bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean onPrepareOptionsMenu(MenuInflater inflater, Menu menu) {
780bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Update the refresh button.
781bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MenuItem item = menu.findItem(R.id.refresh);
782bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (item != null) {
783bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (isRefreshEnabled()) {
784bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                item.setVisible(true);
785bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mRefreshListener.setRefreshIcon(item);
786bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
787bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                item.setVisible(false);
788bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mRefreshListener.setRefreshIcon(null);
789bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
790bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
791bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
792bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Deal with protocol-specific menu options.
793bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean mailboxHasServerCounterpart = false;
794bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean accountSearchable = false;
795bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean isEas = false;
796bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
797bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isMessageListReady()) {
798bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            long accountId = getActualAccountId();
799bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (accountId > 0) {
800bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Account account = Account.restoreAccountWithId(mActivity, accountId);
801bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (account != null) {
802bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    String protocol = account.getProtocol(mActivity);
803bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    isEas = HostAuth.SCHEME_EAS.equals(protocol);
804bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    Mailbox mailbox = getMessageListFragment().getMailbox();
805bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxHasServerCounterpart = (mailbox != null)
806bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            && mailbox.loadsFromServer(protocol);
807bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    accountSearchable = (account.mFlags & Account.FLAGS_SUPPORTS_SEARCH) != 0;
808bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
809bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
810bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
811bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
812bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean showSearchIcon = !mActionBarController.isInSearchMode()
813bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                && accountSearchable && mailboxHasServerCounterpart;
814bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
815bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MenuItem search = menu.findItem(R.id.search);
816bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (search != null) {
817bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            search.setVisible(showSearchIcon);
818bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
819bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MenuItem settings = menu.findItem(R.id.mailbox_settings);
820bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (settings != null) {
821bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            settings.setVisible(isEas && mailboxHasServerCounterpart);
822bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
823bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return true;
824bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
825bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
826bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
827bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the {@link android.app.Activity#onOptionsItemSelected} callback.
828bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
829bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return true if the option item is handled.
830bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
831bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean onOptionsItemSelected(MenuItem item) {
832bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        switch (item.getItemId()) {
833bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case android.R.id.home:
834bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // Comes from the action bar when the app icon on the left is pressed.
835bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // It works like a back press, but it won't close the activity.
836bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return onBackPressed(false);
837bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case R.id.compose:
838bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return onCompose();
839bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case R.id.refresh:
840bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                onRefresh();
841bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return true;
842bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case R.id.account_settings:
843bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return onAccountSettings();
844bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case R.id.search:
845bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                onSearchRequested();
846bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return true;
847bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case R.id.mailbox_settings:
848bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final long mailboxId = getMailboxSettingsMailboxId();
849bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (mailboxId != Mailbox.NO_MAILBOX) {
850bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    MailboxSettings.start(mActivity, mailboxId);
851bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
852bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return true;
853bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
854bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return false;
855bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
856bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
857bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
858bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Opens the message compose activity.
859bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
860bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean onCompose() {
861bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!isAccountSelected()) {
862bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return false; // this shouldn't really happen
863bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
864bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageCompose.actionCompose(mActivity, getActualAccountId());
865bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return true;
866bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
867bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
868bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
869bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handles the "Settings" option item.  Opens the settings activity.
870bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
871bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean onAccountSettings() {
872bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        AccountSettings.actionSettings(mActivity, getActualAccountId());
873bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return true;
874bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
875bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
876bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
877bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the ID of the message in focus and visible, if any. Returns
878bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *     {@link Message#NO_MESSAGE} if no message is opened.
879bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
880bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected long getMessageId() {
881bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isMessageViewInstalled()
882bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ? getMessageViewFragment().getMessageId()
883bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                : Message.NO_MESSAGE;
884bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
885bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
886bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
887bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
888bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return mailbox ID for "mailbox settings" option.
889bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
890bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract long getMailboxSettingsMailboxId();
891bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
892bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
893bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Performs "refesh".
894bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
895bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract void onRefresh();
896bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
897bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
898bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return true if refresh is in progress for the current mailbox.
899bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
900bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract boolean isRefreshInProgress();
901bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
902bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
903bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return true if the UI should enable the "refresh" command.
904bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
905bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract boolean isRefreshEnabled();
906bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
907bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
908bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Refresh the action bar and menu items, including the "refreshing" icon.
909bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
910bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void refreshActionBar() {
911bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mActionBarController != null) {
912bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActionBarController.refresh();
913bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
914bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActivity.invalidateOptionsMenu();
915bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
916bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
917bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // MessageListFragment.Callback
918bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
919bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onMailboxNotFound(boolean isFirstLoad) {
920bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Something bad happened - the account or mailbox we were looking for was deleted.
921bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Just restart and let the entry flow find a good default view.
922bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isFirstLoad) {
923bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Only show this if it's the first load (e.g. a shortcut) rather an a return to
924bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // a mailbox (which might be in a just-deleted account)
925bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Utility.showToast(mActivity, R.string.toast_mailbox_not_found);
926bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
927bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        long accountId = getUIAccountId();
928bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (accountId != Account.NO_ACCOUNT) {
929bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mActivity.startActivity(Welcome.createOpenAccountInboxIntent(mActivity, accountId));
930bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
931bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Welcome.actionStart(mActivity);
932bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
933bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
934bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mActivity.finish();
935bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
936bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
937bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final MessageOrderManager getMessageOrderManager() {
938bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mOrderManager;
939bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
940bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
941bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Perform "auto-advance. */
942bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final void doAutoAdvance() {
943bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        switch (Preferences.getPreferences(mActivity).getAutoAdvanceDirection()) {
944bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case Preferences.AUTO_ADVANCE_NEWER:
945bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (moveToNewer()) return;
946bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                break;
947bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case Preferences.AUTO_ADVANCE_OLDER:
948bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (moveToOlder()) return;
949bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                break;
950bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
951bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isMessageViewInstalled()) { // We really should have the message view but just in case
952bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Go back to mailbox list.
953bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Use onBackPressed(), so we'll restore the message view state, such as scroll
954bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // position.
955bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Also make sure to pass false to isSystemBackKey, so on two-pane we don't go back
956bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // to the collapsed mode.
957bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            onBackPressed(true);
958bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
959bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
960bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
961bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
962bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Subclass must implement it to enable/disable the newer/older buttons.
963bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
964bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract void updateNavigationArrows();
965bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
966bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final boolean moveToOlder() {
967bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if ((mOrderManager != null) && mOrderManager.moveToOlder()) {
968bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            navigateToMessage(mOrderManager.getCurrentMessageId());
969bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return true;
970bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
971bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return false;
972bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
973bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
974bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final boolean moveToNewer() {
975bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if ((mOrderManager != null) && mOrderManager.moveToNewer()) {
976bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            navigateToMessage(mOrderManager.getCurrentMessageId());
977bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return true;
978bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
979bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return false;
980bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
981bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
982bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
983bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Called when the user taps newer/older.  Subclass must implement it to open the specified
984bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * message.
985bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
986bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * It's a bit different from just showing the message view fragment; on one-pane we show the
987bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * message view fragment but don't want to change back state.
988bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
989bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected abstract void navigateToMessage(long messageId);
990bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
991bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
992bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Potentially create a new {@link MessageOrderManager}; if it's not already started or if
993bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the account has changed, and sync it to the current message.
994bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
995bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private void updateMessageOrderManager() {
996bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!isMessageViewInstalled()) {
997bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return;
998bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
999bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Preconditions.checkNotNull(mListContext);
1000bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1001bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mOrderManager == null || !mOrderManager.getListContext().equals(mListContext)) {
1002bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            stopMessageOrderManager();
1003bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mOrderManager = new MessageOrderManager(
1004bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mActivity, mListContext, mMessageOrderManagerCallback);
1005bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
1006bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mOrderManager.moveTo(getMessageId());
1007bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        updateNavigationArrows();
1008bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
1009bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1010bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
1011bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Stop {@link MessageOrderManager}.
1012bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
1013bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected final void stopMessageOrderManager() {
1014bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mOrderManager != null) {
1015bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mOrderManager.close();
1016bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mOrderManager = null;
1017bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
1018bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
1019bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1020bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private class MessageOrderManagerCallback implements MessageOrderManager.Callback {
1021bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
1022bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public void onMessagesChanged() {
1023bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            updateNavigationArrows();
1024bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
1025bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1026bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
1027bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public void onMessageNotFound() {
1028bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            doAutoAdvance();
1029bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
1030bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
1031bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1032bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1033bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private void showAccountSpecificWarning(long accountId) {
1034bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (accountId != Account.NO_ACCOUNT && accountId != Account.NO_ACCOUNT) {
1035bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Account account = Account.restoreAccountWithId(mActivity, accountId);
1036bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (account != null &&
1037bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    Preferences.getPreferences(mActivity)
1038bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    .shouldShowRequireManualSync(mActivity, account)) {
1039bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                new RequireManualSyncDialog(mActivity, account).show();
1040bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
1041bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
1042bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
1043bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
1044bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
1045bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String toString() {
1046bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getClass().getSimpleName(); // Shown on logcat
1047bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
1048bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
1049