Implement 1-pane navigation.
- Now that fragment useage is simplified (e.g. no new fragment creation for nested mailbox navigation), most of the fragment operation code for 2-pane is reuseable for 1-pane as well, so moeved it to the base class. - Temporarily added "Show all folders" as a menu option on 1-pane. - Added "opener account id/mailbox id" to the message view fragment. They are not used by the fragment itself, but they're used by the UI controller for the back navigation. (And now the UI controller doesn't maintain the current IDs by itself; rather it gets them from the currently-active fragment.) - Use async fragment transaction on 1-pane too, now that it always gets the current state from the active fragment. - Changed the timing when we install fragments from onAttachFragment to fragments' onActivityCreated. So now all installed fragments are created. TODO Now that all installed fragments are guaranteed to be created, remove all special trealment for the fragment argument accessor. (They were meant be safe to call before onCreate, but it's not necessary any more.) Change-Id: I0ed100c3f0b460835b164c0dc908ea483a4e46ee
This commit is contained in:
parent
5dc07ad26c
commit
3d9b8e76f0
|
@ -39,6 +39,17 @@
|
|||
android:icon="@drawable/ic_menu_refresh_holo_light"
|
||||
android:showAsAction="ifRoom"
|
||||
/>
|
||||
<!--
|
||||
STOPSHIP "Show all folders" should be in the account spinner, not here.
|
||||
It's temporary UI until we get the ICS style account spinner.
|
||||
-->
|
||||
<item
|
||||
android:id="@+id/show_all_folders"
|
||||
android:orderInCategory="400"
|
||||
android:title="@string/mailbox_list_account_selector_show_all_folders"
|
||||
android:showAsAction="ifRoom"
|
||||
android:visible="false"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/account_settings"
|
||||
android:orderInCategory="2000"
|
||||
|
|
|
@ -265,6 +265,9 @@
|
|||
<!-- Label shown in the account selector to select "Combined view", which contains
|
||||
Combined Inbox, Combined Outbox, etc. [CHAR LIMIT=30] -->
|
||||
<string name="mailbox_list_account_selector_combined_view">Combined view</string>
|
||||
<!-- Label shown in the account/mailbox selector to switch to the show all the top-level
|
||||
mailboxes. [CHAR LIMIT=30] -->
|
||||
<string name="mailbox_list_account_selector_show_all_folders">Show all folders</string>
|
||||
|
||||
<!-- Appears at the bottom of list of messages; user selects to load more messages from that folder. -->
|
||||
<string name="message_list_load_more_messages_action">Load more messages</string>
|
||||
|
|
|
@ -58,7 +58,7 @@ import java.util.ArrayList;
|
|||
* Because this activity is device agnostic, so most of the UI aren't owned by this, but by
|
||||
* the UIController.
|
||||
*/
|
||||
public class EmailActivity extends Activity implements View.OnClickListener {
|
||||
public class EmailActivity extends Activity implements View.OnClickListener, FragmentInstallable {
|
||||
private static final String EXTRA_ACCOUNT_ID = "ACCOUNT_ID";
|
||||
private static final String EXTRA_MAILBOX_ID = "MAILBOX_ID";
|
||||
private static final String EXTRA_MESSAGE_ID = "MESSAGE_ID";
|
||||
|
@ -196,9 +196,6 @@ public class EmailActivity extends Activity implements View.OnClickListener {
|
|||
int errorBannerHeight = getResources().getDimensionPixelSize(R.dimen.error_message_height);
|
||||
mErrorBanner = new BannerController(this, errorMessage, errorBannerHeight);
|
||||
|
||||
// Install restored fragments.
|
||||
mUIController.installRestoredFragments();
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mUIController.restoreInstanceState(savedInstanceState);
|
||||
} else {
|
||||
|
@ -233,12 +230,11 @@ public class EmailActivity extends Activity implements View.OnClickListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onAttachFragment(Fragment fragment) {
|
||||
public void onInstallFragment(Fragment fragment) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, this + " onAttachFragment fragment=" + fragment);
|
||||
Log.d(Logging.LOG_TAG, this + " onInstallFragment fragment=" + fragment);
|
||||
}
|
||||
super.onAttachFragment(fragment);
|
||||
mUIController.onAttachFragment(fragment);
|
||||
mUIController.onInstallFragment(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.email.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
|
||||
/**
|
||||
* Interface for {@link Activity} that can "install" fragments.
|
||||
*/
|
||||
public interface FragmentInstallable {
|
||||
/**
|
||||
* Called when a {@link Fragment} wants to be installed to the host activity.
|
||||
*
|
||||
* Fragments which use this MUST call this from {@link Fragment#onActivityCreated} using
|
||||
* {@link UiUtilities#installFragment}.
|
||||
*
|
||||
* This means a host {@link Activity} can safely assume a passed {@link Fragment} is already
|
||||
* created.
|
||||
*/
|
||||
public void onInstallFragment(Fragment fragment);
|
||||
}
|
|
@ -463,6 +463,8 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
lv.setOnDragListener(this);
|
||||
|
||||
startLoading(mParentMailboxId, mHighlightedMailboxId);
|
||||
|
||||
UiUtilities.installFragment(this);
|
||||
}
|
||||
|
||||
public void setCallback(Callback callback) {
|
||||
|
|
|
@ -394,6 +394,8 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
|
||||
startLoading();
|
||||
|
||||
UiUtilities.installFragment(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,6 +47,8 @@ import android.widget.ImageView;
|
|||
public class MessageViewFragment extends MessageViewFragmentBase
|
||||
implements CheckBox.OnCheckedChangeListener, MoveMessageToDialog.Callback {
|
||||
/** Argument name(s) */
|
||||
private static final String ARG_OPENER_ACCOUNT_ID = "accountId";
|
||||
private static final String ARG_OPENER_MAILBOX_ID = "mailboxId";
|
||||
private static final String ARG_MESSAGE_ID = "messageId";
|
||||
|
||||
private ImageView mFavoriteIcon;
|
||||
|
@ -125,13 +127,33 @@ public class MessageViewFragment extends MessageViewFragmentBase
|
|||
* Create a new instance with initialization parameters.
|
||||
*
|
||||
* This fragment should be created only with this method. (Arguments should always be set.)
|
||||
*
|
||||
* @param openerAccountId account ID that's used in the UI that opened this fragment.
|
||||
* The primary use is for the back navigation to determine which mailbox to show.
|
||||
*
|
||||
* Note this is not necessarily the same ID as the actual account ID for the message.
|
||||
* If a message is opened on the combined view, the caller probably want to pass
|
||||
* {@link Account#ACCOUNT_ID_COMBINED_VIEW} so that back will navigate to the
|
||||
* combined view.
|
||||
*
|
||||
* @param openerMailboxId mailbox ID that's used in the UI that opened this fragment.
|
||||
* The primary use is for the back navigation to determine which mailbox to show.
|
||||
*
|
||||
* Note this is not necessarily the same ID as the actual mailbox ID for the message.
|
||||
* If a message is opened on the combined view, the caller probably want to pass
|
||||
* a combined mailbox ID so that back will navigate to it.
|
||||
*
|
||||
* @param messageId ID of the message to open
|
||||
*/
|
||||
public static MessageViewFragment newInstance(long messageId) {
|
||||
if (messageId == -1) {
|
||||
public static MessageViewFragment newInstance(long openerAccountId, long openerMailboxId,
|
||||
long messageId) {
|
||||
if (messageId == Message.NO_MESSAGE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
final MessageViewFragment instance = new MessageViewFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putLong(ARG_OPENER_ACCOUNT_ID, openerAccountId);
|
||||
args.putLong(ARG_OPENER_MAILBOX_ID, openerMailboxId);
|
||||
args.putLong(ARG_MESSAGE_ID, messageId);
|
||||
instance.setArguments(args);
|
||||
return instance;
|
||||
|
@ -144,10 +166,14 @@ public class MessageViewFragment extends MessageViewFragmentBase
|
|||
* constructs, this <em>must</em> be considered immutable.
|
||||
*/
|
||||
private Long mImmutableMessageId;
|
||||
private Long mImmutableOpenerAccountId;
|
||||
private Long mImmutableOpenerMailboxId;
|
||||
|
||||
private void initializeArgCache() {
|
||||
if (mImmutableMessageId != null) return;
|
||||
mImmutableMessageId = getArguments().getLong(ARG_MESSAGE_ID);
|
||||
mImmutableOpenerAccountId = getArguments().getLong(ARG_OPENER_ACCOUNT_ID);
|
||||
mImmutableOpenerMailboxId = getArguments().getLong(ARG_OPENER_MAILBOX_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,6 +184,22 @@ public class MessageViewFragment extends MessageViewFragmentBase
|
|||
return mImmutableMessageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the account ID passed to {@link #newInstance}. Safe to call even before onCreate.
|
||||
*/
|
||||
public long getOpenerAccountId() {
|
||||
initializeArgCache();
|
||||
return mImmutableOpenerAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mailbox ID passed to {@link #newInstance}. Safe to call even before onCreate.
|
||||
*/
|
||||
public long getOpenerMailboxId() {
|
||||
initializeArgCache();
|
||||
return mImmutableOpenerMailboxId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
|
@ -341,6 +341,8 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
|||
|
||||
resetView();
|
||||
new LoadMessageTask(true).executeParallel();
|
||||
|
||||
UiUtilities.installFragment(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,28 +26,24 @@ import com.android.emailcommon.provider.EmailContent.Message;
|
|||
import com.android.emailcommon.provider.Mailbox;
|
||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Base class for the UI controller.
|
||||
*
|
||||
* Note: Always use {@link #commitFragmentTransaction} to operate fragment transactions,
|
||||
* so that we can easily switch between synchronous and asynchronous transactions.
|
||||
*/
|
||||
abstract class UIControllerBase {
|
||||
protected static final String BUNDLE_KEY_ACCOUNT_ID = "UIController.state.account_id";
|
||||
protected static final String BUNDLE_KEY_MAILBOX_ID = "UIController.state.mailbox_id";
|
||||
protected static final String BUNDLE_KEY_MESSAGE_ID = "UIController.state.message_id";
|
||||
abstract class UIControllerBase implements MailboxListFragment.Callback,
|
||||
MessageListFragment.Callback, MessageViewFragment.Callback {
|
||||
protected static final String BUNDLE_KEY_RESUME_INBOX_LOOKUP
|
||||
= "UIController.state.resumeInboxLookup";
|
||||
protected static final String BUNDLE_KEY_INBOX_LOOKUP_ACCOUNT_ID
|
||||
|
@ -56,26 +52,15 @@ abstract class UIControllerBase {
|
|||
/** The owner activity */
|
||||
final EmailActivity mActivity;
|
||||
|
||||
private final ActionBarController mActionBarController;
|
||||
|
||||
final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
final RefreshManager mRefreshManager;
|
||||
|
||||
/**
|
||||
* List of fragments that are restored by the framework while the activity is being re-created
|
||||
* for configuration changes (e.g. screen rotation). We'll install them later when the activity
|
||||
* is created in {@link #installRestoredFragments()}.
|
||||
*/
|
||||
private final ArrayList<Fragment> mRestoredFragments = new ArrayList<Fragment>();
|
||||
|
||||
/** {@code true} if the activity is resumed. */
|
||||
private boolean mResumed;
|
||||
|
||||
/**
|
||||
* Whether fragment installation should be hold.
|
||||
* We hold installing fragments until {@link #installRestoredFragments()} is called.
|
||||
*/
|
||||
private boolean mHoldFragmentInstallation = true;
|
||||
|
||||
/**
|
||||
* Use to find Inbox. This should only run while the activity is resumed, because otherwise
|
||||
* we may not be able to perform fragment transactions when we get a callback.
|
||||
|
@ -96,34 +81,47 @@ abstract class UIControllerBase {
|
|||
*/
|
||||
private boolean mResumeInboxLookup;
|
||||
|
||||
/**
|
||||
* Fragments that are installed.
|
||||
*
|
||||
* A fragment is installed when:
|
||||
* - it is attached to the activity
|
||||
* - the parent activity is created
|
||||
* - and it is not scheduled to be removed.
|
||||
*
|
||||
* We set callbacks to fragments only when they are installed.
|
||||
*/
|
||||
private MailboxListFragment mMailboxListFragment;
|
||||
private MessageListFragment mMessageListFragment;
|
||||
private MessageViewFragment mMessageViewFragment;
|
||||
|
||||
private final RefreshManager.Listener mRefreshListener
|
||||
= new RefreshManager.Listener() {
|
||||
@Override
|
||||
public void onMessagingError(final long accountId, long mailboxId, final String message) {
|
||||
updateRefreshProgress();
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshStatusChanged(long accountId, long mailboxId) {
|
||||
updateRefreshProgress();
|
||||
refreshActionBar();
|
||||
}
|
||||
};
|
||||
|
||||
public UIControllerBase(EmailActivity activity) {
|
||||
mActivity = activity;
|
||||
mRefreshManager = RefreshManager.getInstance(mActivity);
|
||||
mActionBarController = createActionBarController(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the base class to let a subclass create an {@link ActionBarController}.
|
||||
*/
|
||||
protected abstract ActionBarController createActionBarController(Activity activity);
|
||||
|
||||
/** @return the layout ID for the activity. */
|
||||
public abstract int getLayoutId();
|
||||
|
||||
/**
|
||||
* @return true if the UI controller currently can install fragments.
|
||||
*/
|
||||
protected final boolean isFragmentInstallable() {
|
||||
return !mHoldFragmentInstallation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called just after the activity sets up the content view. Used to initialize views.
|
||||
*
|
||||
|
@ -144,6 +142,7 @@ abstract class UIControllerBase {
|
|||
Log.d(Logging.LOG_TAG, this + " onActivityCreated");
|
||||
}
|
||||
mRefreshManager.registerListener(mRefreshListener);
|
||||
mActionBarController.onActivityCreated();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,30 +196,10 @@ abstract class UIControllerBase {
|
|||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, this + " onActivityDestroy");
|
||||
}
|
||||
mHoldFragmentInstallation = true; // No more fragment installation.
|
||||
mRefreshManager.unregisterListener(mRefreshListener);
|
||||
mTaskTracker.cancellAllInterrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install all the fragments kept in {@link #mRestoredFragments}.
|
||||
*
|
||||
* Must be called at the end of {@link EmailActivity#onCreate}.
|
||||
*/
|
||||
public final void installRestoredFragments() {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, this + " installRestoredFragments");
|
||||
}
|
||||
|
||||
mHoldFragmentInstallation = false;
|
||||
|
||||
// Install all the fragments restored by the framework.
|
||||
for (Fragment fragment : mRestoredFragments) {
|
||||
installFragment(fragment);
|
||||
}
|
||||
mRestoredFragments.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link android.app.Activity#onSaveInstanceState} callback.
|
||||
*/
|
||||
|
@ -244,24 +223,12 @@ abstract class UIControllerBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link android.app.Activity#onAttachFragment} callback.
|
||||
*
|
||||
* If the activity has already been created, we initialize the fragment here. Otherwise we
|
||||
* keep the fragment in {@link #mRestoredFragments} and initialize it after the activity's
|
||||
* onCreate.
|
||||
* Install a fragment. Must be caleld from the host activity's
|
||||
* {@link FragmentInstallable#onInstallFragment}.
|
||||
*/
|
||||
public final void onAttachFragment(Fragment fragment) {
|
||||
if (mHoldFragmentInstallation) {
|
||||
// Fragment being restored by the framework during the activity recreation.
|
||||
mRestoredFragments.add(fragment);
|
||||
return;
|
||||
}
|
||||
installFragment(fragment);
|
||||
}
|
||||
|
||||
private void installFragment(Fragment fragment) {
|
||||
public final void onInstallFragment(Fragment fragment) {
|
||||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, this + " installFragment fragment=" + fragment);
|
||||
Log.d(Logging.LOG_TAG, this + " onInstallFragment fragment=" + fragment);
|
||||
}
|
||||
if (fragment instanceof MailboxListFragment) {
|
||||
installMailboxListFragment((MailboxListFragment) fragment);
|
||||
|
@ -270,15 +237,114 @@ abstract class UIControllerBase {
|
|||
} else if (fragment instanceof MessageViewFragment) {
|
||||
installMessageViewFragment((MessageViewFragment) fragment);
|
||||
} else {
|
||||
// Ignore -- uninteresting fragments such as dialogs.
|
||||
throw new IllegalArgumentException("Tried to install unknown fragment");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void installMailboxListFragment(MailboxListFragment fragment);
|
||||
/** Install fragment */
|
||||
protected void installMailboxListFragment(MailboxListFragment fragment) {
|
||||
mMailboxListFragment = fragment;
|
||||
mMailboxListFragment.setCallback(this);
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
protected abstract void installMessageListFragment(MessageListFragment fragment);
|
||||
/** Install fragment */
|
||||
protected void installMessageListFragment(MessageListFragment fragment) {
|
||||
mMessageListFragment = fragment;
|
||||
mMessageListFragment.setCallback(this);
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
protected abstract void installMessageViewFragment(MessageViewFragment fragment);
|
||||
/** Install fragment */
|
||||
protected void installMessageViewFragment(MessageViewFragment fragment) {
|
||||
mMessageViewFragment = fragment;
|
||||
mMessageViewFragment.setCallback(this);
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall - If the fragment is installed, remove it from the given
|
||||
* {@link FragmentTransaction} and also clears the callabck.
|
||||
*/
|
||||
protected FragmentTransaction uninstallMailboxListFragment(FragmentTransaction ft) {
|
||||
if (isMailboxListInstalled()) {
|
||||
onMailboxListFragmentUninstalled(mMailboxListFragment);
|
||||
ft.remove(mMailboxListFragment);
|
||||
mMailboxListFragment.setCallback(null);
|
||||
mMailboxListFragment = null;
|
||||
}
|
||||
return ft;
|
||||
}
|
||||
|
||||
/** Called when a {@link MailboxListFragment} is about to be uninstalled */
|
||||
protected void onMailboxListFragmentUninstalled(MailboxListFragment fragment) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall - If the fragment is installed, remove it from the given
|
||||
* {@link FragmentTransaction} and also clears the callabck.
|
||||
*/
|
||||
protected FragmentTransaction uninstallMessageListFragment(FragmentTransaction ft) {
|
||||
if (isMessageListInstalled()) {
|
||||
onMessageListFragmentUninstalled(mMessageListFragment);
|
||||
ft.remove(mMessageListFragment);
|
||||
mMessageListFragment.setCallback(null);
|
||||
mMessageListFragment = null;
|
||||
}
|
||||
return ft;
|
||||
}
|
||||
|
||||
/** Called when a {@link MessageListFragment} is about to be uninstalled */
|
||||
protected void onMessageListFragmentUninstalled(MessageListFragment fragment) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall - If the fragment is installed, remove it from the given
|
||||
* {@link FragmentTransaction} and also clears the callabck.
|
||||
*/
|
||||
protected FragmentTransaction uninstallMessageViewFragment(FragmentTransaction ft) {
|
||||
if (isMessageViewInstalled()) {
|
||||
onMessageViewFragmentUninstalled(mMessageViewFragment);
|
||||
ft.remove(mMessageViewFragment);
|
||||
mMessageViewFragment.setCallback(null);
|
||||
mMessageViewFragment = null;
|
||||
}
|
||||
return ft;
|
||||
}
|
||||
|
||||
/** Called when a {@link MessageViewFragment} is about to be uninstalled */
|
||||
protected void onMessageViewFragmentUninstalled(MessageViewFragment fragment) {
|
||||
}
|
||||
|
||||
/** @return true if a {@link MailboxListFragment} is installed. */
|
||||
protected final boolean isMailboxListInstalled() {
|
||||
return mMailboxListFragment != null;
|
||||
}
|
||||
|
||||
/** @return true if a {@link MessageListFragment} is installed. */
|
||||
protected final boolean isMessageListInstalled() {
|
||||
return mMessageListFragment != null;
|
||||
}
|
||||
|
||||
/** @return true if a {@link MessageViewFragment} is installed. */
|
||||
protected final boolean isMessageViewInstalled() {
|
||||
return mMessageViewFragment != null;
|
||||
}
|
||||
|
||||
/** @return the installed {@link MailboxListFragment} or null. */
|
||||
protected final MailboxListFragment getMailboxListFragment() {
|
||||
return mMailboxListFragment;
|
||||
}
|
||||
|
||||
/** @return the installed {@link MessageListFragment} or null. */
|
||||
protected final MessageListFragment getMessageListFragment() {
|
||||
return mMessageListFragment;
|
||||
}
|
||||
|
||||
/** @return the installed {@link MessageViewFragment} or null. */
|
||||
protected final MessageViewFragment getMessageViewFragment() {
|
||||
return mMessageViewFragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit a {@link FragmentTransaction}.
|
||||
|
@ -535,14 +601,13 @@ abstract class UIControllerBase {
|
|||
*/
|
||||
protected abstract boolean isRefreshEnabled();
|
||||
|
||||
|
||||
/**
|
||||
* Start/stop the "refresh" animation on the action bar according to the current refresh state.
|
||||
*
|
||||
* (We start the animation if {@link #isRefreshInProgress} returns true,
|
||||
* and stop otherwise.)
|
||||
* Refresh the action bar and menu items, including the "refreshing" icon.
|
||||
*/
|
||||
protected void updateRefreshProgress() {
|
||||
protected void refreshActionBar() {
|
||||
if (mActionBarController != null) {
|
||||
mActionBarController.refresh();
|
||||
}
|
||||
mActivity.invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,16 +19,21 @@ package com.android.email.activity;
|
|||
import com.android.email.Email;
|
||||
import com.android.email.R;
|
||||
import com.android.email.activity.MailboxFinder.Callback;
|
||||
import com.android.email.activity.setup.AccountSecurity;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
import com.android.emailcommon.provider.Mailbox;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
|
||||
import android.app.FragmentManager;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -36,183 +41,179 @@ import java.util.Set;
|
|||
/**
|
||||
* UI Controller for non x-large devices. Supports a single-pane layout.
|
||||
*
|
||||
* STOPSHIP Everything in this class is 100% temporary at this point
|
||||
* - Navigation model is different from what it should be (whatever it'll be).
|
||||
* e.g. when the app is launched, we should show Inbox, not mailbox list.
|
||||
* One one-pane, multiple fragments can be installed at the same time, but only one of them
|
||||
* can be "visible" at a time. Others are in the back stack. Use {@link #isMailboxListVisible()},
|
||||
* {@link #isMessageListVisible()} and {@link #isMessageViewVisible()} to determine which is
|
||||
* visible.
|
||||
*
|
||||
* - It uses the two-pane action bar only so that we can change accounts
|
||||
* Note due to the asynchronous nature of the fragment transaction, there is a window when
|
||||
* there is no installed or visible fragments.
|
||||
*
|
||||
* TODO Use the back stack for the message list -> message view navigation, so that the list
|
||||
* position/selection will be restored on back.
|
||||
*
|
||||
* Major TODOs
|
||||
* - TODO Proper Navigation model, including retaining fragments to keep state such as the scroll
|
||||
* position and batch selection.
|
||||
* - TODO Nested folders
|
||||
* - TODO Newer/Older for message view with swipe!
|
||||
* - TODO Implement callbacks
|
||||
*/
|
||||
class UIControllerOnePane extends UIControllerBase {
|
||||
private ActionBarController mActionBarController;
|
||||
|
||||
/**
|
||||
* Current account/mailbox/message IDs.
|
||||
* Don't use them directly; use the accessors instead, as we might want to get them from the
|
||||
* topmost fragment in the future.
|
||||
*/
|
||||
private long mCurrentAccountId = Account.NO_ACCOUNT;
|
||||
private long mCurrentMailboxId = Mailbox.NO_MAILBOX;
|
||||
private long mCurrentMessageId = Message.NO_MESSAGE;
|
||||
|
||||
// TODO Newer/Older buttons not needed. Remove this.
|
||||
private MessageCommandButtonView mMessageCommandButtons;
|
||||
|
||||
private final MailboxListFragment.Callback mMailboxListFragmentCallback =
|
||||
new MailboxListFragment.Callback() {
|
||||
@Override
|
||||
public void onAccountSelected(long accountId) {
|
||||
switchAccount(accountId);
|
||||
// MailboxListFragment.Callback
|
||||
@Override
|
||||
public void onAccountSelected(long accountId) {
|
||||
switchAccount(accountId);
|
||||
}
|
||||
|
||||
// MailboxListFragment.Callback
|
||||
@Override
|
||||
public void onCurrentMailboxUpdated(long mailboxId, String mailboxName, int unreadCount) {
|
||||
}
|
||||
|
||||
// MailboxListFragment.Callback
|
||||
@Override
|
||||
public void onMailboxSelected(long accountId, long mailboxId, boolean nestedNavigation) {
|
||||
if (nestedNavigation) {
|
||||
return; // Nothing to do on 1-pane.
|
||||
}
|
||||
openMailbox(accountId, mailboxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentMailboxUpdated(long mailboxId, String mailboxName, int unreadCount) {
|
||||
// MailboxListFragment.Callback
|
||||
@Override
|
||||
public void onParentMailboxChanged() {
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onAdvancingOpAccepted(Set<Long> affectedMessages) {
|
||||
// Nothing to do on 1 pane.
|
||||
}
|
||||
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onEnterSelectionMode(boolean enter) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onListLoaded() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onMailboxNotFound() {
|
||||
open(getUIAccountId(), Mailbox.NO_MAILBOX, Message.NO_MESSAGE);
|
||||
}
|
||||
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onMessageOpen(
|
||||
long messageId, long messageMailboxId, long listMailboxId, int type) {
|
||||
if (type == MessageListFragment.Callback.TYPE_DRAFT) {
|
||||
MessageCompose.actionEditDraft(mActivity, messageId);
|
||||
} else {
|
||||
open(getUIAccountId(), getMailboxId(), messageId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMailboxSelected(long accountId, long mailboxId, boolean nestedNavigation) {
|
||||
if (nestedNavigation) {
|
||||
return; // Nothing to do on 1-pane.
|
||||
}
|
||||
openMailbox(accountId, mailboxId);
|
||||
}
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public boolean onDragStarted() {
|
||||
// No drag&drop on 1-pane
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParentMailboxChanged() {
|
||||
refreshActionBar();
|
||||
}
|
||||
};
|
||||
// MessageListFragment.Callback
|
||||
@Override
|
||||
public void onDragEnded() {
|
||||
// No drag&drop on 1-pane
|
||||
}
|
||||
|
||||
private final MessageListFragment.Callback mMessageListFragmentCallback =
|
||||
new MessageListFragment.Callback() {
|
||||
@Override
|
||||
public void onAdvancingOpAccepted(Set<Long> affectedMessages) {
|
||||
// Nothing to do on 1 pane.
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onForward() {
|
||||
MessageCompose.actionForward(mActivity, getMessageId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterSelectionMode(boolean enter) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onReply() {
|
||||
MessageCompose.actionReply(mActivity, getMessageId(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListLoaded() {
|
||||
// TODO Auto-generated method stub
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onReplyAll() {
|
||||
MessageCompose.actionReply(mActivity, getMessageId(), true);
|
||||
}
|
||||
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onCalendarLinkClicked(long epochEventStartTime) {
|
||||
ActivityHelper.openCalendar(mActivity, epochEventStartTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMailboxNotFound() {
|
||||
open(getUIAccountId(), Mailbox.NO_MAILBOX, Message.NO_MESSAGE);
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public boolean onUrlInMessageClicked(String url) {
|
||||
return ActivityHelper.openUrlInMessage(mActivity, url, getActualAccountId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageOpen(
|
||||
long messageId, long messageMailboxId, long listMailboxId, int type) {
|
||||
if (type == MessageListFragment.Callback.TYPE_DRAFT) {
|
||||
MessageCompose.actionEditDraft(mActivity, messageId);
|
||||
} else {
|
||||
open(getUIAccountId(), getMailboxId(), messageId);
|
||||
}
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onBeforeMessageGone() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDragStarted() {
|
||||
// No drag&drop on 1-pane
|
||||
return false;
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onMessageSetUnread() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragEnded() {
|
||||
// No drag&drop on 1-pane
|
||||
}
|
||||
};
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onRespondedToInvite(int response) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
private final MessageViewFragment.Callback mMessageViewFragmentCallback =
|
||||
new MessageViewFragment.Callback() {
|
||||
@Override
|
||||
public void onForward() {
|
||||
MessageCompose.actionForward(mActivity, getMessageId());
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onLoadMessageError(String errorMessage) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReply() {
|
||||
MessageCompose.actionReply(mActivity, getMessageId(), false);
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onLoadMessageFinished() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplyAll() {
|
||||
MessageCompose.actionReply(mActivity, getMessageId(), true);
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onLoadMessageStarted() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalendarLinkClicked(long epochEventStartTime) {
|
||||
ActivityHelper.openCalendar(mActivity, epochEventStartTime);
|
||||
}
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onMessageNotExists() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUrlInMessageClicked(String url) {
|
||||
return ActivityHelper.openUrlInMessage(mActivity, url, getActualAccountId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeMessageGone() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageSetUnread() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRespondedToInvite(int response) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMessageError(String errorMessage) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMessageFinished() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadMessageStarted() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageNotExists() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessageShown() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
};
|
||||
// MessageViewFragment.Callback
|
||||
@Override
|
||||
public void onMessageShown() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
// This is all temporary as we'll have a different action bar controller for 1-pane.
|
||||
private final ActionBarController.Callback mActionBarControllerCallback
|
||||
= new ActionBarController.Callback() {
|
||||
private class ActionBarControllerCallback implements ActionBarController.Callback {
|
||||
@Override
|
||||
public boolean shouldShowMailboxName() {
|
||||
return false; // no mailbox name/unread count.
|
||||
|
@ -230,8 +231,8 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
|
||||
@Override
|
||||
public boolean shouldShowUp() {
|
||||
// Always show the UP arrow.
|
||||
return true;
|
||||
return isMessageViewVisible()
|
||||
|| (isMailboxListVisible() && !getMailboxListFragment().isRoot());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -254,37 +255,30 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
Welcome.actionStart(mActivity);
|
||||
mActivity.finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public UIControllerOnePane(EmailActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* At this point we use synchronous transactions.
|
||||
*/
|
||||
@Override
|
||||
protected void commitFragmentTransaction(FragmentTransaction ft) {
|
||||
super.commitFragmentTransaction(ft);
|
||||
mActivity.getFragmentManager().executePendingTransactions();
|
||||
protected ActionBarController createActionBarController(Activity activity) {
|
||||
|
||||
// For now, we just reuse the same action bar controller used for 2-pane.
|
||||
// We may change it later.
|
||||
|
||||
return new ActionBarController(activity, activity.getLoaderManager(),
|
||||
activity.getActionBar(), new ActionBarControllerCallback());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putLong(BUNDLE_KEY_ACCOUNT_ID, mCurrentAccountId);
|
||||
outState.putLong(BUNDLE_KEY_MAILBOX_ID, mCurrentMailboxId);
|
||||
outState.putLong(BUNDLE_KEY_MESSAGE_ID, mCurrentMessageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreInstanceState(Bundle savedInstanceState) {
|
||||
super.restoreInstanceState(savedInstanceState);
|
||||
mCurrentAccountId = savedInstanceState.getLong(BUNDLE_KEY_ACCOUNT_ID, Account.NO_ACCOUNT);
|
||||
mCurrentMailboxId = savedInstanceState.getLong(BUNDLE_KEY_MAILBOX_ID, Mailbox.NO_MAILBOX);
|
||||
mCurrentMessageId = savedInstanceState.getLong(BUNDLE_KEY_MESSAGE_ID, Message.NO_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -295,8 +289,6 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
@Override
|
||||
public void onActivityViewReady() {
|
||||
super.onActivityViewReady();
|
||||
mActionBarController = new ActionBarController(mActivity, mActivity.getLoaderManager(),
|
||||
mActivity.getActionBar(), mActionBarControllerCallback);
|
||||
|
||||
mMessageCommandButtons = UiUtilities.getView(mActivity, R.id.message_command_buttons);
|
||||
mMessageCommandButtons.setCallback(new CommandButtonCallback());
|
||||
|
@ -305,7 +297,6 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
@Override
|
||||
public void onActivityCreated() {
|
||||
super.onActivityCreated();
|
||||
mActionBarController.onActivityCreated();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -314,76 +305,96 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
refreshActionBar();
|
||||
}
|
||||
|
||||
/** @return true if a {@link MailboxListFragment} is installed and visible. */
|
||||
private final boolean isMailboxListVisible() {
|
||||
return isMailboxListInstalled();
|
||||
}
|
||||
|
||||
/** @return true if a {@link MessageListFragment} is installed and visible. */
|
||||
private final boolean isMessageListVisible() {
|
||||
return isMessageListInstalled();
|
||||
}
|
||||
|
||||
/** @return true if a {@link MessageViewFragment} is installed and visible. */
|
||||
private final boolean isMessageViewVisible() {
|
||||
return isMessageViewInstalled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUIAccountId() {
|
||||
return mCurrentAccountId;
|
||||
// Get it from the visible fragment.
|
||||
if (isMailboxListVisible()) {
|
||||
return getMailboxListFragment().getAccountId();
|
||||
}
|
||||
if (isMessageListVisible()) {
|
||||
return getMessageListFragment().getAccountId();
|
||||
}
|
||||
if (isMessageViewVisible()) {
|
||||
return getMessageViewFragment().getOpenerAccountId();
|
||||
}
|
||||
return Account.NO_ACCOUNT;
|
||||
}
|
||||
|
||||
private long getMailboxId() {
|
||||
return mCurrentMailboxId;
|
||||
// Get it from the visible fragment.
|
||||
if (isMessageListVisible()) {
|
||||
return getMessageListFragment().getMailboxId();
|
||||
}
|
||||
if (isMessageViewVisible()) {
|
||||
return getMessageViewFragment().getOpenerMailboxId();
|
||||
}
|
||||
return Mailbox.NO_MAILBOX;
|
||||
}
|
||||
|
||||
private long getMessageId() {
|
||||
return mCurrentMessageId;
|
||||
// Get it from the visible fragment.
|
||||
if (isMessageViewVisible()) {
|
||||
return getMessageViewFragment().getMessageId();
|
||||
}
|
||||
return Message.NO_MESSAGE;
|
||||
}
|
||||
|
||||
private final MailboxFinder.Callback mInboxLookupCallback = new MailboxFinder.Callback() {
|
||||
@Override
|
||||
public void onMailboxFound(long accountId, long mailboxId) {
|
||||
// Inbox found.
|
||||
openMailbox(accountId, mailboxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccountNotFound() {
|
||||
// Account removed?
|
||||
Welcome.actionStart(mActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMailboxNotFound(long accountId) {
|
||||
// Inbox not found??
|
||||
Welcome.actionStart(mActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccountSecurityHold(long accountId) {
|
||||
mActivity.startActivity(AccountSecurity.actionUpdateSecurityIntent(mActivity, accountId,
|
||||
true));
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected Callback getInboxLookupCallback() {
|
||||
// We don't call startInboxLookup in UIControllerOnePane, so shouldn't be called.
|
||||
throw new RuntimeException("SHOULD NOT BE CALLED"); // STOPSHIP
|
||||
}
|
||||
|
||||
private void refreshActionBar() {
|
||||
if (mActionBarController != null) {
|
||||
mActionBarController.refresh();
|
||||
}
|
||||
mActivity.invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private boolean isMailboxListVisible() {
|
||||
return (getMailboxId() == Mailbox.NO_MAILBOX);
|
||||
}
|
||||
|
||||
private boolean isMessageListVisible() {
|
||||
return (getMailboxId() != Mailbox.NO_MAILBOX) && (getMessageId() == Message.NO_MESSAGE);
|
||||
}
|
||||
|
||||
private boolean isMessageViewVisible() {
|
||||
return (getMailboxId() != Mailbox.NO_MAILBOX) && (getMessageId() != Message.NO_MESSAGE);
|
||||
return mInboxLookupCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(boolean isSystemBackKey) {
|
||||
if (isMessageViewVisible()) {
|
||||
open(getUIAccountId(), getMailboxId(), Message.NO_MESSAGE);
|
||||
openMailbox(getMessageViewFragment().getOpenerAccountId(),
|
||||
getMessageViewFragment().getOpenerMailboxId());
|
||||
return true;
|
||||
} else if (isMessageListVisible()) {
|
||||
open(getUIAccountId(), Mailbox.NO_MAILBOX, Message.NO_MESSAGE);
|
||||
} else if (isMailboxListVisible() && getMailboxListFragment().navigateUp()) {
|
||||
return true;
|
||||
} else {
|
||||
// TODO Call MailboxListFragment.navigateUp().
|
||||
|
||||
// STOPSHIP Remove this and return false. This is so that the app can be closed
|
||||
// with the UP press. (usuful when the device doesn't have a HW back key.)
|
||||
mActivity.finish();
|
||||
return true;
|
||||
// return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installMailboxListFragment(MailboxListFragment fragment) {
|
||||
fragment.setCallback(mMailboxListFragmentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installMessageListFragment(MessageListFragment fragment) {
|
||||
fragment.setCallback(mMessageListFragmentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installMessageViewFragment(MessageViewFragment fragment) {
|
||||
fragment.setCallback(mMessageViewFragmentCallback);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -396,40 +407,63 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// !!! It's all temporary to make 1 pane UI (barely) usable !!!
|
||||
//
|
||||
// - Nested folders still doesn't work
|
||||
// - When opening a child view (e.g. message list -> message view), we should retain
|
||||
// the current fragment so that all the state (selection, scroll position, etc) will be
|
||||
// restored when back.
|
||||
|
||||
if ((getUIAccountId() == accountId) && (getMailboxId() == mailboxId)
|
||||
&& (getMessageId() == messageId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final FragmentManager fm = mActivity.getFragmentManager();
|
||||
final FragmentTransaction ft = fm.beginTransaction();
|
||||
|
||||
if (messageId != Message.NO_MESSAGE) {
|
||||
ft.replace(R.id.fragment_placeholder, MessageViewFragment.newInstance(messageId));
|
||||
|
||||
showMessageView(accountId, mailboxId, messageId);
|
||||
} else if (mailboxId != Mailbox.NO_MAILBOX) {
|
||||
ft.replace(R.id.fragment_placeholder, MessageListFragment.newInstance(
|
||||
accountId, mailboxId));
|
||||
|
||||
showMessageList(accountId, mailboxId);
|
||||
} else {
|
||||
ft.replace(R.id.fragment_placeholder,
|
||||
MailboxListFragment.newInstance(accountId, Mailbox.NO_MAILBOX, false));
|
||||
// Mailbox not specified. Open Inbox or Combined Inbox.
|
||||
if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||
showMessageList(accountId, Mailbox.QUERY_ALL_INBOXES);
|
||||
} else {
|
||||
startInboxLookup(accountId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentAccountId = accountId;
|
||||
mCurrentMailboxId = mailboxId;
|
||||
mCurrentMessageId = messageId;
|
||||
private void uninstallAllFragments(FragmentTransaction ft) {
|
||||
if (isMailboxListInstalled()) {
|
||||
uninstallMailboxListFragment(ft);
|
||||
}
|
||||
if (isMessageListInstalled()) {
|
||||
uninstallMessageListFragment(ft);
|
||||
}
|
||||
if (isMessageViewInstalled()) {
|
||||
uninstallMessageViewFragment(ft);
|
||||
}
|
||||
}
|
||||
|
||||
private void showMailboxList(long accountId, long mailboxId) {
|
||||
showFragment(MailboxListFragment.newInstance(accountId, mailboxId, false));
|
||||
}
|
||||
|
||||
private void showMessageList(long accountId, long mailboxId) {
|
||||
showFragment(MessageListFragment.newInstance(accountId, mailboxId));
|
||||
}
|
||||
|
||||
private void showMessageView(long accountId, long mailboxId, long messageId) {
|
||||
showFragment(MessageViewFragment.newInstance(accountId, mailboxId, messageId));
|
||||
}
|
||||
|
||||
private void showFragment(Fragment fragment) {
|
||||
final FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
|
||||
uninstallAllFragments(ft);
|
||||
ft.add(R.id.fragment_placeholder, fragment);
|
||||
commitFragmentTransaction(ft);
|
||||
}
|
||||
|
||||
refreshActionBar();
|
||||
private void showAllMailboxes() {
|
||||
if (!isAccountSelected()) {
|
||||
return; // Can happen because of asyncronous fragment transactions.
|
||||
}
|
||||
// Don't use open(account, NO_MAILBOX, NO_MESSAGE). This is used to open the default
|
||||
// view, which is Inbox on the message list.
|
||||
showMailboxList(getUIAccountId(), Mailbox.NO_MAILBOX);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -495,4 +529,21 @@ class UIControllerOnePane extends UIControllerBase {
|
|||
return mRefreshManager.isMailboxListRefreshing(getActualAccountId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(MenuInflater inflater, Menu menu) {
|
||||
// STOPSHIP For temporary menu item which should be visible only on 1-pane.
|
||||
menu.findItem(R.id.show_all_folders).setVisible(true);
|
||||
return super.onPrepareOptionsMenu(inflater, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.show_all_folders: // STOPSHIP For temporary menu item
|
||||
showAllMailboxes();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,27 +54,9 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
@VisibleForTesting
|
||||
static final int INBOX_AUTO_REFRESH_MIN_INTERVAL = 10 * 1000; // in milliseconds
|
||||
|
||||
private ActionBarController mActionBarController;
|
||||
private final ActionBarControllerCallback mActionBarControllerCallback =
|
||||
new ActionBarControllerCallback();
|
||||
|
||||
// Other UI elements
|
||||
private ThreePaneLayout mThreePane;
|
||||
|
||||
/**
|
||||
* Fragments that are installed.
|
||||
*
|
||||
* A fragment is installed when:
|
||||
* - it is attached to the activity
|
||||
* - the parent activity is created
|
||||
* - and it is not scheduled to be removed.
|
||||
*
|
||||
* We set callbacks to fragments only when they are installed.
|
||||
*/
|
||||
private MailboxListFragment mMailboxListFragment;
|
||||
private MessageListFragment mMessageListFragment;
|
||||
private MessageViewFragment mMessageViewFragment;
|
||||
|
||||
private MessageCommandButtonView mMessageCommandButtons;
|
||||
|
||||
private MessageOrderManager mOrderManager;
|
||||
|
@ -100,12 +82,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
FragmentManager.enableDebugLogging(true);
|
||||
}
|
||||
|
||||
private void refreshActionBar() {
|
||||
if (mActionBarController != null) {
|
||||
mActionBarController.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.email_activity_two_pane;
|
||||
|
@ -163,7 +139,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
}
|
||||
// Disable CAB when the message list is not visible.
|
||||
if (isMessageListInstalled()) {
|
||||
mMessageListFragment.onHidden((visiblePanes & ThreePaneLayout.PANE_MIDDLE) == 0);
|
||||
getMessageListFragment().onHidden((visiblePanes & ThreePaneLayout.PANE_MIDDLE) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,8 +353,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
@Override
|
||||
public void onActivityViewReady() {
|
||||
super.onActivityViewReady();
|
||||
mActionBarController = new ActionBarController(mActivity, mActivity.getLoaderManager(),
|
||||
mActivity.getActionBar(), mActionBarControllerCallback);
|
||||
|
||||
// Set up content
|
||||
mThreePane = (ThreePaneLayout) mActivity.findViewById(R.id.three_pane);
|
||||
|
@ -388,6 +362,12 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
mMessageCommandButtons.setCallback(new CommandButtonCallback());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActionBarController createActionBarController(Activity activity) {
|
||||
return new ActionBarController(activity, activity.getLoaderManager(),
|
||||
activity.getActionBar(), new ActionBarControllerCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currently selected account ID, *or* {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
|
||||
*
|
||||
|
@ -395,7 +375,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
*/
|
||||
@Override
|
||||
public long getUIAccountId() {
|
||||
return isMailboxListInstalled() ? mMailboxListFragment.getAccountId()
|
||||
return isMailboxListInstalled() ? getMailboxListFragment().getAccountId()
|
||||
:Account.NO_ACCOUNT;
|
||||
}
|
||||
|
||||
|
@ -406,7 +386,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
* {@link #getMessageListMailboxId()}
|
||||
*/
|
||||
private long getMailboxListMailboxId() {
|
||||
return isMailboxListInstalled() ? mMailboxListFragment.getSelectedMailboxId()
|
||||
return isMailboxListInstalled() ? getMailboxListFragment().getSelectedMailboxId()
|
||||
: Mailbox.NO_MAILBOX;
|
||||
}
|
||||
|
||||
|
@ -417,7 +397,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
* {@link #getMessageListMailboxId()}
|
||||
*/
|
||||
private long getMessageListMailboxId() {
|
||||
return isMessageListInstalled() ? mMessageListFragment.getMailboxId()
|
||||
return isMessageListInstalled() ? getMessageListFragment().getMailboxId()
|
||||
: Message.NO_MESSAGE;
|
||||
}
|
||||
|
||||
|
@ -438,23 +418,10 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
}
|
||||
|
||||
private long getMessageId() {
|
||||
return isMessageViewInstalled() ? mMessageViewFragment.getMessageId()
|
||||
return isMessageViewInstalled() ? getMessageViewFragment().getMessageId()
|
||||
: Message.NO_MESSAGE;
|
||||
}
|
||||
|
||||
private boolean isMailboxListInstalled() {
|
||||
return mMailboxListFragment != null;
|
||||
}
|
||||
|
||||
private boolean isMessageListInstalled() {
|
||||
return mMessageListFragment != null;
|
||||
}
|
||||
|
||||
private boolean isMessageViewInstalled() {
|
||||
return mMessageViewFragment != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if refresh is in progress for the current mailbox.
|
||||
*/
|
||||
|
@ -481,7 +448,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
@Override
|
||||
public void onActivityCreated() {
|
||||
super.onActivityCreated();
|
||||
mActionBarController.onActivityCreated();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
@ -536,67 +502,28 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installMailboxListFragment(MailboxListFragment fragment) {
|
||||
mMailboxListFragment = fragment;
|
||||
mMailboxListFragment.setCallback(this);
|
||||
|
||||
// Update action bar / menu
|
||||
updateRefreshProgress();
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installMessageListFragment(MessageListFragment fragment) {
|
||||
mMessageListFragment = fragment;
|
||||
mMessageListFragment.setCallback(this);
|
||||
super.installMessageListFragment(fragment);
|
||||
|
||||
if (isMailboxListInstalled()) {
|
||||
mMailboxListFragment.setHighlightedMailbox(mMessageListFragment.getMailboxId());
|
||||
getMailboxListFragment().setHighlightedMailbox(fragment.getMailboxId());
|
||||
}
|
||||
|
||||
// Update action bar / menu
|
||||
updateRefreshProgress();
|
||||
refreshActionBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installMessageViewFragment(MessageViewFragment fragment) {
|
||||
mMessageViewFragment = fragment;
|
||||
mMessageViewFragment.setCallback(this);
|
||||
super.installMessageViewFragment(fragment);
|
||||
|
||||
if (isMessageListInstalled()) {
|
||||
mMessageListFragment.setSelectedMessage(mMessageViewFragment.getMessageId());
|
||||
getMessageListFragment().setSelectedMessage(fragment.getMessageId());
|
||||
}
|
||||
}
|
||||
|
||||
private FragmentTransaction uninstallMailboxListFragment(FragmentTransaction ft) {
|
||||
if (isMailboxListInstalled()) {
|
||||
ft.remove(mMailboxListFragment);
|
||||
mMailboxListFragment.setCallback(null);
|
||||
mMailboxListFragment = null;
|
||||
}
|
||||
return ft;
|
||||
}
|
||||
|
||||
private FragmentTransaction uninstallMessageListFragment(FragmentTransaction ft) {
|
||||
if (isMessageListInstalled()) {
|
||||
ft.remove(mMessageListFragment);
|
||||
mMessageListFragment.setCallback(null);
|
||||
mMessageListFragment = null;
|
||||
}
|
||||
return ft;
|
||||
}
|
||||
|
||||
private FragmentTransaction uninstallMessageViewFragment(FragmentTransaction ft) {
|
||||
if (isMessageViewInstalled()) {
|
||||
ft.remove(mMessageViewFragment);
|
||||
mMessageViewFragment.setCallback(null);
|
||||
mMessageViewFragment = null;
|
||||
// Don't need it when there's no message view.
|
||||
stopMessageOrderManager();
|
||||
}
|
||||
return ft;
|
||||
@Override
|
||||
protected void onMessageViewFragmentUninstalled(MessageViewFragment fragment) {
|
||||
// Don't need it when there's no message view.
|
||||
stopMessageOrderManager();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -638,20 +565,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
commitFragmentTransaction(ft);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-fragment transaction check.
|
||||
*
|
||||
* @throw IllegalStateException if updateXxx methods can't be called in the current state.
|
||||
*/
|
||||
private void preFragmentTransactionCheck() {
|
||||
if (!isFragmentInstallable()) {
|
||||
// Code assumes mMailboxListFragment/etc are set right within the
|
||||
// commitFragmentTransaction() call (because we use synchronous transaction),
|
||||
// so updateXxx() can't be called if fragments are not installable yet.
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given account and optionally selects the given mailbox and message. If the
|
||||
* specified account is already selected, no actions will be performed unless
|
||||
|
@ -669,12 +582,10 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
Log.d(Logging.LOG_TAG, this + " updateMailboxList accountId=" + accountId
|
||||
+ " mailboxId=" + mailboxId);
|
||||
}
|
||||
preFragmentTransactionCheck();
|
||||
if (accountId == Account.NO_ACCOUNT) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
|
||||
if ((getUIAccountId() != accountId) || (getMailboxListMailboxId() != mailboxId)) {
|
||||
uninstallMailboxListFragment(ft);
|
||||
ft.add(mThreePane.getLeftPaneId(),
|
||||
|
@ -721,7 +632,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, this + " updateMessageList mMailboxId=" + mailboxId);
|
||||
}
|
||||
preFragmentTransactionCheck();
|
||||
if (mailboxId == Mailbox.NO_MAILBOX) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
@ -758,7 +668,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, this + " updateMessageView messageId=" + messageId);
|
||||
}
|
||||
preFragmentTransactionCheck();
|
||||
if (messageId == Message.NO_MESSAGE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
@ -768,7 +677,9 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
}
|
||||
|
||||
uninstallMessageViewFragment(ft);
|
||||
ft.add(mThreePane.getRightPaneId(), MessageViewFragment.newInstance(messageId));
|
||||
|
||||
ft.add(mThreePane.getRightPaneId(), MessageViewFragment.newInstance(
|
||||
getUIAccountId(), getMessageListMailboxId(), messageId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -786,8 +697,8 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
private void unselectMessage() {
|
||||
commitFragmentTransaction(uninstallMessageViewFragment(
|
||||
mActivity.getFragmentManager().beginTransaction()));
|
||||
if (mMessageListFragment != null) {
|
||||
mMessageListFragment.setSelectedMessage(Message.NO_MESSAGE);
|
||||
if (isMessageListInstalled()) {
|
||||
getMessageListFragment().setSelectedMessage(Message.NO_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -891,7 +802,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
public boolean onBackPressed(boolean isSystemBackKey) {
|
||||
if (mThreePane.onBackPressed(isSystemBackKey)) {
|
||||
return true;
|
||||
} else if (isMailboxListInstalled() && mMailboxListFragment.navigateUp()) {
|
||||
} else if (isMailboxListInstalled() && getMailboxListFragment().navigateUp()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1061,7 +972,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
|||
final int visiblePanes = mThreePane.getVisiblePanes();
|
||||
final boolean leftPaneHidden = ((visiblePanes & ThreePaneLayout.PANE_LEFT) == 0);
|
||||
return leftPaneHidden
|
||||
|| (isMailboxListInstalled() && !mMailboxListFragment.isRoot());
|
||||
|| (isMailboxListInstalled() && !getMailboxListFragment().isRoot());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.email.activity;
|
|||
import com.android.email.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
|
@ -123,4 +124,16 @@ public class UiUtilities {
|
|||
public static void setVisibilitySafe(View parent, int viewId, int visibility) {
|
||||
setVisibilitySafe(parent.findViewById(viewId), visibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by an {@link Fragment} to install itself to the host activity.
|
||||
*
|
||||
* @see FragmentInstallable
|
||||
*/
|
||||
public static void installFragment(Fragment fragment) {
|
||||
final Activity a = fragment.getActivity();
|
||||
if (a instanceof FragmentInstallable) {
|
||||
((FragmentInstallable) a).onInstallFragment(fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue