Merge "Define roles for fragment manager and activity"

This commit is contained in:
Todd Kennedy 2011-04-04 10:50:19 -07:00 committed by Android (Google) Code Review
commit 22f06c371b
2 changed files with 428 additions and 556 deletions

View File

@ -21,7 +21,6 @@ import com.android.email.Controller;
import com.android.email.ControllerResultUiThreadWrapper;
import com.android.email.Email;
import com.android.email.MessagingExceptionStrings;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.RefreshManager;
import com.android.email.activity.setup.AccountSecurity;
@ -43,6 +42,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@ -51,12 +51,11 @@ import android.widget.TextView;
import java.security.InvalidParameterException;
/**
* The main (two-pane) activity for XL devices.
*
* TODO Refine "move to".
* The main activity for multi-pane UIs. The <code>MessageListXL</code> class is responsible
* for managing the "chrome" area of the screen; which primarily includes the action bar.
* The rest of the content area is managed by a fragment manager.
*/
public class MessageListXL extends Activity implements
MessageListXLFragmentManager.TargetActivity, MoveMessageToDialog.Callback,
public class MessageListXL extends Activity implements MessageListXLFragmentManager.TargetActivity,
View.OnClickListener {
private static final String EXTRA_ACCOUNT_ID = "ACCOUNT_ID";
private static final String EXTRA_MAILBOX_ID = "MAILBOX_ID";
@ -71,28 +70,22 @@ public class MessageListXL extends Activity implements
private final RefreshListener mRefreshListener = new RefreshListener();
private Controller.Result mControllerResult;
/** True between onCreate() to onDestroy() */
private boolean mIsCreated;
private AccountSelectorAdapter mAccountsSelectorAdapter;
private final ActionBarNavigationCallback mActionBarNavigationCallback
= new ActionBarNavigationCallback();
private ActionBar mActionBar;
private View mActionBarMailboxNameView;
private TextView mActionBarMailboxName;
private TextView mActionBarUnreadCount;
private final ActionBarNavigationCallback mActionBarNavigationCallback =
new ActionBarNavigationCallback();
private MessageOrderManager mOrderManager;
private final MessageListXLFragmentManager mFragmentManager
= new MessageListXLFragmentManager(this);
private final MessageOrderManagerCallback mMessageOrderManagerCallback
= new MessageOrderManagerCallback();
private final MessageListXLFragmentManager mFragmentManager =
new MessageListXLFragmentManager(this);
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
private BannerController mBannerController;
private TextView mErrorMessageView;
/**
* Id of the account that had a messaging exception most recently.
*/
/** Banner to display errors */
private BannerController mErrorBanner;
/** Id of the account that had a messaging exception most recently. */
private long mLastErrorAccountId;
/**
@ -162,10 +155,6 @@ public class MessageListXL extends Activity implements
mRefreshManager = RefreshManager.getInstance(this);
mRefreshManager.registerListener(mRefreshListener);
mFragmentManager.setMailboxListFragmentCallback(new MailboxListFragmentCallback());
mFragmentManager.setMessageListFragmentCallback(new MessageListFragmentCallback());
mFragmentManager.setMessageViewFragmentCallback(new MessageViewFragmentCallback());
mAccountsSelectorAdapter = new AccountSelectorAdapter(this, null);
if (savedInstanceState != null) {
@ -178,10 +167,28 @@ public class MessageListXL extends Activity implements
// Set up views
// TODO Probably better to extract mErrorMessageView related code into a separate class,
// so that it'll be easy to reuse for the phone activities.
mErrorMessageView = (TextView) findViewById(R.id.error_message);
mErrorMessageView.setOnClickListener(this);
mBannerController = new BannerController(this, mErrorMessageView,
getResources().getDimensionPixelSize(R.dimen.error_message_height));
TextView errorMessage = (TextView) findViewById(R.id.error_message);
errorMessage.setOnClickListener(this);
int errorBannerHeight = getResources().getDimensionPixelSize(R.dimen.error_message_height);
mErrorBanner = new BannerController(this, errorMessage, errorBannerHeight);
mActionBar = getActionBar();
// Set a view for the current mailbox to the action bar.
final LayoutInflater inflater = LayoutInflater.from(mContext);
mActionBarMailboxNameView = inflater.inflate(R.layout.action_bar_current_mailbox, null);
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
final ActionBar.LayoutParams customViewLayout = new ActionBar.LayoutParams(
ActionBar.LayoutParams.WRAP_CONTENT,
ActionBar.LayoutParams.MATCH_PARENT);
customViewLayout.setMargins(mContext.getResources().getDimensionPixelSize(
R.dimen.action_bar_mailbox_name_left_margin) , 0, 0, 0);
mActionBar.setCustomView(mActionBarMailboxNameView, customViewLayout);
mActionBarMailboxName =
(TextView) mActionBarMailboxNameView.findViewById(R.id.mailbox_name);
mActionBarUnreadCount =
(TextView) mActionBarMailboxNameView.findViewById(R.id.unread_count);
// Halt the progress indicator (we'll display it later when needed)
setProgressBarIndeterminate(true);
@ -190,8 +197,6 @@ public class MessageListXL extends Activity implements
mControllerResult = new ControllerResultUiThreadWrapper<ControllerResult>(new Handler(),
new ControllerResult());
mController.addResultCallback(mControllerResult);
mIsCreated = true;
}
private void initFromIntent() {
@ -221,11 +226,7 @@ public class MessageListXL extends Activity implements
protected void onStart() {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) Log.d(Logging.LOG_TAG, "MessageListXL onStart");
super.onStart();
mFragmentManager.onStart();
if (mFragmentManager.isMessageSelected()) {
updateMessageOrderManager();
}
}
@Override
@ -233,12 +234,12 @@ public class MessageListXL extends Activity implements
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) Log.d(Logging.LOG_TAG, "MessageListXL onResume");
super.onResume();
mFragmentManager.onResume();
// On MessageList.onResume, we go back to Welcome if an account has been added/removed.
// We don't need to do that here, because when the activity resumes, the account list loader
// will load the latest list.
// And if all the accounts have been removed, the loader will detect it and do
// appropriate things.
/**
* In {@link MessageList#onResume()}, we go back to {@link Welcome} if an account
* has been added/removed. We don't need to do that here, because we fetch the most
* up-to-date account list. Additionally, we detect and do the right thing if all
* of the accounts have been removed.
*/
}
@Override
@ -252,15 +253,12 @@ public class MessageListXL extends Activity implements
protected void onStop() {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) Log.d(Logging.LOG_TAG, "MessageListXL onStop");
super.onStop();
mFragmentManager.onStop();
stopMessageOrderManager();
}
@Override
protected void onDestroy() {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) Log.d(Logging.LOG_TAG, "MessageListXL onDestroy");
mIsCreated = false;
mController.removeResultCallback(mControllerResult);
mTaskTracker.cancellAllInterrupt();
mRefreshManager.unregisterListener(mRefreshListener);
@ -279,8 +277,8 @@ public class MessageListXL extends Activity implements
/**
* Performs the back action.
*
* @param isSystemBackKey set true if the system back key is pressed, rather than the home
* icon on action bar.
* @param isSystemBackKey <code>true</code> if the system back key was pressed. Otherwise,
* <code>false</code> [e.g. the home icon on action bar were pressed].
*/
private boolean onBackPressed(boolean isSystemBackKey) {
if (mFragmentManager.onBackPressed(isSystemBackKey)) {
@ -303,237 +301,6 @@ public class MessageListXL extends Activity implements
}
}
private void onCurrentMessageGone() {
switch (Preferences.getPreferences(this).getAutoAdvanceDirection()) {
case Preferences.AUTO_ADVANCE_NEWER:
if (moveToNewer()) return;
if (moveToOlder()) return;
break;
case Preferences.AUTO_ADVANCE_OLDER:
if (moveToOlder()) return;
if (moveToNewer()) return;
break;
}
// Last message in the box or AUTO_ADVANCE_MESSAGE_LIST. Go back to message list.
mFragmentManager.goBackToMailbox();
}
private void onMoveMessage() {
long messageId = mFragmentManager.getMessageId();
MoveMessageToDialog dialog = MoveMessageToDialog.newInstance(new long[] {messageId},
null);
dialog.show(getFragmentManager(), "dialog");
}
@Override
public void onMoveToMailboxSelected(long newMailboxId, long[] messageIds) {
ActivityHelper.moveMessages(this, newMailboxId, messageIds);
onCurrentMessageGone();
}
/**
* Start {@link MessageOrderManager} if not started, and sync it to the current message.
*/
private void updateMessageOrderManager() {
if (!mFragmentManager.isMailboxSelected()) {
return;
}
final long mailboxId = mFragmentManager.getMailboxId();
if (mOrderManager == null || mOrderManager.getMailboxId() != mailboxId) {
stopMessageOrderManager();
mOrderManager = new MessageOrderManager(this, mailboxId, mMessageOrderManagerCallback);
}
if (mFragmentManager.isMessageSelected()) {
mOrderManager.moveTo(mFragmentManager.getMessageId());
}
}
private class MessageOrderManagerCallback implements MessageOrderManager.Callback {
@Override
public void onMessagesChanged() {
updateNavigationArrows();
}
@Override
public void onMessageNotFound() {
// Current message gone.
mFragmentManager.goBackToMailbox();
}
}
/**
* Stop {@link MessageOrderManager}.
*/
private void stopMessageOrderManager() {
if (mOrderManager != null) {
mOrderManager.close();
mOrderManager = null;
}
}
/**
* Called when the default account is not found, i.e. there's no account set up.
*/
private void onNoAccountFound() {
// Open Welcome, which in turn shows the adding a new account screen.
Welcome.actionStart(this);
finish();
return;
}
/**
* Disable/enable the move-to-newer/older buttons.
*/
private void updateNavigationArrows() {
if (mOrderManager == null) {
// shouldn't happen, but just in case
mFragmentManager.updateMessageCommandButtons(false, false, 0, 0);
} else {
mFragmentManager.updateMessageCommandButtons(
mOrderManager.canMoveToNewer(), mOrderManager.canMoveToOlder(),
mOrderManager.getCurrentPosition(), mOrderManager.getTotalMessageCount());
}
}
private boolean moveToOlder() {
if (mFragmentManager.isMessageSelected() && (mOrderManager != null)
&& mOrderManager.moveToOlder()) {
mFragmentManager.selectMessage(mOrderManager.getCurrentMessageId());
return true;
}
return false;
}
private boolean moveToNewer() {
if (mFragmentManager.isMessageSelected() && (mOrderManager != null)
&& mOrderManager.moveToNewer()) {
mFragmentManager.selectMessage(mOrderManager.getCurrentMessageId());
return true;
}
return false;
}
private class MailboxListFragmentCallback implements MailboxListFragment.Callback {
@Override
public void onMailboxSelected(long accountId, long mailboxId) {
mFragmentManager.selectMailbox(mailboxId, -1);
}
@Override
public void onAccountSelected(long accountId) {
mFragmentManager.selectAccount(accountId, -1, -1);
loadAccounts(); // This will update the account spinner, and select the account.
}
@Override
public void onCurrentMailboxUpdated(long mailboxId, String mailboxName, int unreadCount) {
mFragmentManager.setCurrentMailboxName(mailboxName, unreadCount);
}
}
private class MessageListFragmentCallback implements MessageListFragment.Callback {
@Override
public void onListLoaded() {
}
@Override
public void onMessageOpen(long messageId, long messageMailboxId, long listMailboxId,
int type) {
if (type == MessageListFragment.Callback.TYPE_DRAFT) {
MessageCompose.actionEditDraft(MessageListXL.this, messageId);
} else {
mFragmentManager.selectMessage(messageId);
}
}
@Override
public void onMailboxNotFound() {
// TODO: What to do??
}
@Override
public void onEnterSelectionMode(boolean enter) {
}
}
private class MessageViewFragmentCallback implements MessageViewFragment.Callback {
@Override
public void onMessageViewShown(int mailboxType) {
updateMessageOrderManager();
updateNavigationArrows();
}
@Override
public void onMessageViewGone() {
stopMessageOrderManager();
}
@Override
public boolean onUrlInMessageClicked(String url) {
return ActivityHelper.openUrlInMessage(MessageListXL.this, url,
mFragmentManager.getActualAccountId());
}
@Override
public void onMessageSetUnread() {
mFragmentManager.goBackToMailbox();
}
@Override
public void onMessageNotExists() {
mFragmentManager.goBackToMailbox();
}
@Override
public void onLoadMessageStarted() {
// TODO Any nice UI for this?
}
@Override
public void onLoadMessageFinished() {
// TODO Any nice UI for this?
}
@Override
public void onLoadMessageError(String errorMessage) {
}
@Override
public void onRespondedToInvite(int response) {
onCurrentMessageGone();
}
@Override
public void onCalendarLinkClicked(long epochEventStartTime) {
ActivityHelper.openCalendar(MessageListXL.this, epochEventStartTime);
}
@Override
public void onBeforeMessageDelete() {
onCurrentMessageGone();
}
@Override
public void onMoveMessage() {
MessageListXL.this.onMoveMessage();
}
@Override
public void onForward() {
MessageCompose.actionForward(MessageListXL.this, mFragmentManager.getMessageId());
}
@Override
public void onReply() {
MessageCompose.actionReply(MessageListXL.this, mFragmentManager.getMessageId(), false);
}
@Override
public void onReplyAll() {
MessageCompose.actionReply(MessageListXL.this, mFragmentManager.getMessageId(), true);
}
}
@Override
public void onAccountSecurityHold(long accountId) {
startActivity(AccountSecurity.actionUpdateSecurityIntent(this, accountId, true));
@ -542,6 +309,7 @@ public class MessageListXL extends Activity implements
@Override
public void onAccountChanged(long accountId) {
invalidateOptionsMenu(); // Update the refresh button
loadAccounts(); // This will update the account spinner, and select the account.
}
@Override
@ -550,57 +318,20 @@ public class MessageListXL extends Activity implements
}
@Override
public void onMoveToNewer() {
moveToNewer();
}
public void onMailboxNameChanged(String mailboxName, int unreadCount) {
mActionBarMailboxName.setText(mailboxName);
@Override
public void onMoveToOlder() {
moveToOlder();
}
/**
* Call this when getting a connection error.
*/
private void showErrorMessage(final String rawMessage, final long accountId) {
new EmailAsyncTask<Void, Void, String>(mTaskTracker) {
@Override
protected String doInBackground(Void... params) {
Account account = Account.restoreAccountWithId(MessageListXL.this, accountId);
return (account == null) ? null : account.mDisplayName;
}
@Override
protected void onPostExecute(String accountName) {
final String message;
if (TextUtils.isEmpty(accountName)) {
message = rawMessage;
} else {
// TODO Use properly designed layout. Don't just concat strings, which isn't
// good for I18N either.
message = rawMessage + " (" + accountName + ")";
}
if (mBannerController.show(message)) {
mLastErrorAccountId = accountId;
}
}
}.executeParallel();
}
/**
* Call this when the connection for an account is considered working.
*/
private void clearErrorMessage(long accountId) {
if (mLastErrorAccountId == accountId) {
dismissErrorMessage();
}
// Note on action bar, we show only "unread count". Some mailboxes such as Outbox don't
// have the idea of "unread count", in which case we just omit the count.
mActionBarUnreadCount.setText(
UiUtilities.getMessageCountForUi(mContext, unreadCount, true));
}
/**
* Force dismiss the error banner.
*/
private void dismissErrorMessage() {
mBannerController.dismiss();
mErrorBanner.dismiss();
}
/**
@ -632,7 +363,9 @@ public class MessageListXL extends Activity implements
private void updateAccountList(Cursor accountsCursor) {
final int count = accountsCursor.getCount();
if (count == 0) {
onNoAccountFound();
// Open Welcome, which in turn shows the adding a new account screen.
Welcome.actionStart(this);
finish();
return;
}
@ -645,8 +378,6 @@ public class MessageListXL extends Activity implements
ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setTitle(AccountSelectorAdapter.getAccountDisplayName(accountsCursor));
selectAccount(AccountSelectorAdapter.getAccountId(accountsCursor));
return;
}
@ -772,6 +503,16 @@ public class MessageListXL extends Activity implements
mFragmentManager.getMailboxId()).cancelPreviousAndExecuteParallel();
}
@Override
public void onVisiblePanesChanged(int visiblePanes) {
// If the left pane (mailbox list pane) is hidden, the back action on action bar will be
// enabled, and we also show the current mailbox name.
final boolean leftPaneHidden = ((visiblePanes & ThreePaneLayout.PANE_LEFT) == 0);
mActionBar.setDisplayOptions(leftPaneHidden ? ActionBar.DISPLAY_HOME_AS_UP : 0,
ActionBar.DISPLAY_HOME_AS_UP);
mActionBarMailboxNameView.setVisibility(leftPaneHidden ? View.VISIBLE : View.GONE);
}
/**
* Class to handle refresh.
*
@ -917,20 +658,42 @@ public class MessageListXL extends Activity implements
handleError(result, accountId, progress);
}
private void handleError(MessagingException result, long accountId, int progress) {
private void handleError(final MessagingException result, final long accountId,
int progress) {
if (accountId == -1) {
return;
}
if (result == null) {
if (progress > 0) {
// Connection now working.
clearErrorMessage(accountId);
// Connection now working; clear the error message banner
if (mLastErrorAccountId == accountId) {
dismissErrorMessage();
}
}
} else {
// Connection error.
showErrorMessage(
MessagingExceptionStrings.getErrorString(MessageListXL.this, result),
accountId);
// Connection error; show the error message banner
new EmailAsyncTask<Void, Void, String>(mTaskTracker) {
@Override
protected String doInBackground(Void... params) {
Account account =
Account.restoreAccountWithId(MessageListXL.this, accountId);
return (account == null) ? null : account.mDisplayName;
}
@Override
protected void onPostExecute(String accountName) {
String message =
MessagingExceptionStrings.getErrorString(MessageListXL.this, result);
if (!TextUtils.isEmpty(accountName)) {
// TODO Use properly designed layout. Don't just concatenate strings;
// which is generally poor for I18N.
message = message + " (" + accountName + ")";
}
if (mErrorBanner.show(message)) {
mLastErrorAccountId = accountId;
}
}
}.executeParallel();
}
}
}

View File

@ -17,20 +17,18 @@
package com.android.email.activity;
import com.android.email.Email;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Mailbox;
import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.security.InvalidParameterException;
@ -42,16 +40,22 @@ import java.security.InvalidParameterException;
*
* TODO: Test it. It's testable if we implement MockFragmentTransaction, which may be too early
* to do so at this point. (API may not be stable enough yet.)
*
* TODO Refine "move to".
*/
class MessageListXLFragmentManager {
class MessageListXLFragmentManager implements
MoveMessageToDialog.Callback,
MailboxFinder.Callback,
ThreePaneLayout.Callback,
MailboxListFragment.Callback,
MessageListFragment.Callback,
MessageViewFragment.Callback {
private static final String BUNDLE_KEY_ACCOUNT_ID = "MessageListXl.state.account_id";
private static final String BUNDLE_KEY_MAILBOX_ID = "MessageListXl.state.mailbox_id";
private static final String BUNDLE_KEY_MESSAGE_ID = "MessageListXl.state.message_id";
private static final String BUNDLE_KEY_MESSAGE_LIST_STATE
= "MessageListXl.state.message_list_state";
private final Context mContext;
private boolean mIsActivityResumed;
/** Current account id. (-1 = not selected) */
@ -63,11 +67,7 @@ class MessageListXLFragmentManager {
/** Current message id. (-1 = not selected) */
private long mMessageId = -1;
private ActionBar mActionBar;
private ThreePaneLayout mThreePane;
private View mActionBarMailboxNameView;
private TextView mActionBarMailboxName;
private TextView mActionBarUnreadCount;
private MailboxListFragment mMailboxListFragment;
private MessageListFragment mMessageListFragment;
@ -75,52 +75,216 @@ class MessageListXLFragmentManager {
private MessageCommandButtonView mMessageCommandButtons;
private MailboxFinder mMailboxFinder;
private final MailboxFinderCallback mMailboxFinderCallback = new MailboxFinderCallback();
private final ThreePaneLayoutCallback mThreePaneLayoutCallback = new ThreePaneLayoutCallback();
/**
* Save state for the "message list -> message view -[back press]-> message list" transition.
*/
/** Save state for the "message list -> message view -[back press]-> message list" transition */
private MessageListFragment.State mMessageListFragmentState;
private MessageOrderManager mOrderManager;
private final MessageOrderManagerCallback mMessageOrderManagerCallback =
new MessageOrderManagerCallback();
/**
* The interface that {@link MessageListXL} implements. We don't call its methods directly,
* in the hope that it'll make writing tests easier, and make it clear which methods are needed
* for MessageListXLFragmentManager.
* TODO Consider getting rid of this. The fragment manager needs an {@link Activity}, so,
* merely passing around an interface is not sufficient.
*/
public interface TargetActivity {
/** Implemented by {@link Activity}, so, signature must match */
public ActionBar getActionBar();
public FragmentManager getFragmentManager();
/**
* Called when the selected account is on security-hold.
*/
public void onAccountSecurityHold(long accountId);
/**
* Called when the current account has changed.
*/
public void onAccountChanged(long accountId);
/**
* Called when the current mailbox has changed.
*/
public void onMailboxChanged(long accountId, long newMailboxId);
/** Called when "move to newer" button is pressed. */
public void onMoveToNewer();
/** Called when "move to older" button is pressed. */
public void onMoveToOlder();
public View findViewById(int id);
/** Called when the selected account is on security-hold. */
public void onAccountSecurityHold(long accountId);
/** Called when the current account has changed. */
public void onAccountChanged(long accountId);
/** Called when the current mailbox has changed. */
public void onMailboxChanged(long accountId, long newMailboxId);
/** Called when the current mailbox name / unread count has changed. */
public void onMailboxNameChanged(String mailboxName, int unreadCount);
/** Called when the visible panes have changed. */
public void onVisiblePanesChanged(int visiblePanes);
}
private final TargetActivity mTargetActivity;
private final MessageListXL mActivity;
public MessageListXLFragmentManager(MessageListXL activity) {
mContext = activity;
mTargetActivity = activity;
mActivity = activity;
}
// MailboxFinder$Callback
@Override
public void onAccountNotFound() {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MessageListXLFragmentManager#onAccountNotFound()");
}
// Shouldn't happen
}
@Override
public void onAccountSecurityHold(long accountId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MessageListXLFragmentManager#onAccountSecurityHold()");
}
mActivity.onAccountSecurityHold(accountId);
}
@Override
public void onMailboxFound(long accountId, long mailboxId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MessageListXLFragmentManager#onMailboxFound()");
}
selectMailbox(mailboxId, -1);
}
@Override
public void onMailboxNotFound(long accountId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MessageListXLFragmentManager#onMailboxNotFound()");
}
// Shouldn't happen
}
// MoveMessageToDialog$Callback
@Override
public void onMoveToMailboxSelected(long newMailboxId, long[] messageIds) {
ActivityHelper.moveMessages(mActivity, newMailboxId, messageIds);
onCurrentMessageGone();
}
// ThreePaneLayoutCallback
@Override
public void onVisiblePanesChanged(int previousVisiblePanes) {
final int visiblePanes = mThreePane.getVisiblePanes();
mActivity.onVisiblePanesChanged(visiblePanes);
if (((visiblePanes & ThreePaneLayout.PANE_RIGHT) == 0) &&
((previousVisiblePanes & ThreePaneLayout.PANE_RIGHT) != 0)) {
// Message view just got hidden
mMessageId = -1;
mMessageListFragment.setSelectedMessage(-1);
mMessageViewFragment.clearContent();
}
mMessageListFragment.setVisibility((visiblePanes & ThreePaneLayout.PANE_MIDDLE) != 0);
}
// MailboxListFragment$Callback
@Override
public void onMailboxSelected(long accountId, long mailboxId) {
selectMailbox(mailboxId, -1);
}
@Override
public void onAccountSelected(long accountId) {
selectAccount(accountId, -1, -1);
}
@Override
public void onCurrentMailboxUpdated(long mailboxId, String mailboxName, int unreadCount) {
mActivity.onMailboxNameChanged(mailboxName, unreadCount);
}
// 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 {
selectMessage(messageId);
}
}
@Override
public void onMailboxNotFound() {
// TODO: What to do??
}
@Override
public void onEnterSelectionMode(boolean enter) {
}
@Override
public void onListLoaded() {
}
// MessageViewFragment$Callback
@Override
public void onMessageViewShown(int mailboxType) {
updateMessageOrderManager();
updateNavigationArrows();
}
@Override
public void onMessageViewGone() {
stopMessageOrderManager();
}
@Override
public boolean onUrlInMessageClicked(String url) {
return ActivityHelper.openUrlInMessage(mActivity, url, getActualAccountId());
}
@Override
public void onMessageSetUnread() {
goBackToMailbox();
}
@Override
public void onMessageNotExists() {
goBackToMailbox();
}
@Override
public void onLoadMessageStarted() {
// TODO Any nice UI for this?
}
@Override
public void onLoadMessageFinished() {
// TODO Any nice UI for this?
}
@Override
public void onLoadMessageError(String errorMessage) {
}
@Override
public void onRespondedToInvite(int response) {
onCurrentMessageGone();
}
@Override
public void onCalendarLinkClicked(long epochEventStartTime) {
ActivityHelper.openCalendar(mActivity, epochEventStartTime);
}
@Override
public void onBeforeMessageDelete() {
onCurrentMessageGone();
}
@Override
public void onMoveMessage() {
long messageId = getMessageId();
MoveMessageToDialog dialog = MoveMessageToDialog.newInstance(new long[] {messageId}, null);
dialog.show(mActivity.getFragmentManager(), "dialog");
}
@Override
public void onForward() {
MessageCompose.actionForward(mActivity, getMessageId());
}
@Override
public void onReply() {
MessageCompose.actionReply(mActivity, getMessageId(), false);
}
@Override
public void onReplyAll() {
MessageCompose.actionReply(mActivity, getMessageId(), true);
}
/**
@ -133,10 +297,10 @@ class MessageListXLFragmentManager {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MessageListXLFragmentManager.onActivityViewReady");
}
mThreePane = (ThreePaneLayout) mTargetActivity.findViewById(R.id.three_pane);
mThreePane.setCallback(mThreePaneLayoutCallback);
mThreePane = (ThreePaneLayout) mActivity.findViewById(R.id.three_pane);
mThreePane.setCallback(this);
FragmentManager fm = mTargetActivity.getFragmentManager();
FragmentManager fm = mActivity.getFragmentManager();
mMailboxListFragment = (MailboxListFragment) fm.findFragmentById(
mThreePane.getLeftPaneId());
mMessageListFragment = (MessageListFragment) fm.findFragmentById(
@ -146,41 +310,9 @@ class MessageListXLFragmentManager {
mMessageCommandButtons = mThreePane.getMessageCommandButtons();
mMessageCommandButtons.setCallback(new CommandButtonCallback());
mActionBar = mTargetActivity.getActionBar();
// Set a view for the current mailbox to the action bar.
final LayoutInflater inflater = LayoutInflater.from(mContext);
mActionBarMailboxNameView = inflater.inflate(R.layout.action_bar_current_mailbox, null);
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
final ActionBar.LayoutParams customViewLayout = new ActionBar.LayoutParams(
ActionBar.LayoutParams.WRAP_CONTENT,
ActionBar.LayoutParams.MATCH_PARENT);
customViewLayout.setMargins(mContext.getResources().getDimensionPixelSize(
R.dimen.action_bar_mailbox_name_left_margin) , 0, 0, 0);
mActionBar.setCustomView(mActionBarMailboxNameView, customViewLayout);
mActionBarMailboxName =
(TextView) mActionBarMailboxNameView.findViewById(R.id.mailbox_name);
mActionBarUnreadCount =
(TextView) mActionBarMailboxNameView.findViewById(R.id.unread_count);
}
/** Set callback for fragment. */
public void setMailboxListFragmentCallback(
MailboxListFragment.Callback mailboxListFragmentCallback) {
mMailboxListFragment.setCallback(mailboxListFragmentCallback);
}
/** Set callback for fragment. */
public void setMessageListFragmentCallback(
MessageListFragment.Callback messageListFragmentCallback) {
mMessageListFragment.setCallback(messageListFragmentCallback);
}
/** Set callback for fragment. */
public void setMessageViewFragmentCallback(
MessageViewFragment.Callback messageViewFragmentCallback) {
mMessageViewFragment.setCallback(messageViewFragmentCallback);
mMailboxListFragment.setCallback(this);
mMessageListFragment.setCallback(this);
mMessageViewFragment.setCallback(this);
}
/**
@ -225,35 +357,26 @@ class MessageListXLFragmentManager {
return getMessageId() != -1;
}
public MailboxListFragment getMailboxListFragment() {
return mMailboxListFragment;
}
public MessageListFragment getMessageListFragment() {
return mMessageListFragment;
}
public MessageViewFragment getMessageViewFragment() {
return mMessageViewFragment;
}
/**
* Called from {@link MessageListXL#onStart}.
*/
public void onStart() {
// Nothing to do
if (isMessageSelected()) {
updateMessageOrderManager();
}
}
/**
* Called from {@link MessageListXL#onResume}.
*/
public void onResume() {
int visiblePanes = mThreePane.getVisiblePanes();
mActivity.onVisiblePanesChanged(visiblePanes);
if (mIsActivityResumed) {
return;
}
mIsActivityResumed = true;
updateActionBar();
}
/**
@ -264,14 +387,14 @@ class MessageListXLFragmentManager {
return;
}
mIsActivityResumed = false;
saveMessageListFragmentState();
mMessageListFragmentState = mMessageListFragment.getState();
}
/**
* Called from {@link MessageListXL#onStop}.
*/
public void onStop() {
// Nothing to do
stopMessageOrderManager();
}
/**
@ -304,38 +427,6 @@ class MessageListXLFragmentManager {
selectAccount(accountId, mailboxId, messageId);
}
private void saveMessageListFragmentState() {
if (mMessageListFragment != null) {
mMessageListFragmentState = mMessageListFragment.getState();
}
}
private void restoreMesasgeListState() {
if ((mMessageListFragment != null) && (mMessageListFragmentState != null)) {
mMessageListFragmentState.restore(mMessageListFragment);
mMessageListFragmentState = null;
}
}
private void updateActionBar() {
// If the left pane (mailbox list pane) is hidden, the back action on action bar will be
// enabled, and we also show the current mailbox name.
final int visiblePanes = mThreePane.getVisiblePanes();
final boolean leftPaneHidden = ((visiblePanes & ThreePaneLayout.PANE_LEFT) == 0);
mActionBar.setDisplayOptions(leftPaneHidden ? ActionBar.DISPLAY_HOME_AS_UP : 0,
ActionBar.DISPLAY_HOME_AS_UP);
mActionBarMailboxNameView.setVisibility(leftPaneHidden ? View.VISIBLE : View.GONE);
}
public void setCurrentMailboxName(String mailboxName, int unreadCount) {
mActionBarMailboxName.setText(mailboxName);
// Note on action bar, we show only "unread count". Some mailboxes such as Outbox don't
// have the idea of "unread count", in which case we just omit the count.
mActionBarUnreadCount.setText(
UiUtilities.getMessageCountForUi(mContext, unreadCount, true));
}
/**
* Call it to select an account.
*
@ -371,11 +462,14 @@ class MessageListXLFragmentManager {
// When opening the Combined view, the right pane will be "combined inbox".
selectMailbox(Mailbox.QUERY_ALL_INBOXES, -1);
} else if (mailboxId == -1) {
startInboxLookup();
// Try to find the inbox for the account
closeMailboxFinder();
mMailboxFinder = new MailboxFinder(mActivity, mAccountId, Mailbox.TYPE_INBOX, this);
mMailboxFinder.startLookup();
} else {
selectMailbox(mailboxId, messageId);
}
mTargetActivity.onAccountChanged(mAccountId);
mActivity.onAccountChanged(mAccountId);
}
/**
@ -389,59 +483,61 @@ class MessageListXLFragmentManager {
}
/**
* If the current view is MessageView, go back to MessageList.
* Go back to a mailbox list view. If a message view is currently active, it will
* be hidden.
*/
public void goBackToMailbox() {
private void goBackToMailbox() {
if (isMessageSelected()) {
mThreePane.showLeftPane(); // Show mailbox list
}
}
/**
* Call it to select a mailbox.
*
* Select a mailbox and potentially a message within that mailbox.
* We assume the mailbox selected here belongs to the account selected with
* {@link #selectAccount}.
*
* @param mailboxId ID of mailbox
* @param messageId message ID. Pass -1 to not open a message.
*/
public void selectMailbox(long mailboxId, long messageId) {
private void selectMailbox(long mailboxId, long messageId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "selectMailbox mMailboxId=" + mailboxId);
}
if (mailboxId == -1) {
throw new InvalidParameterException();
}
if (mMailboxId == mailboxId) {
return;
}
// Update members.
// Update members
mMailboxId = mailboxId;
mMessageId = -1;
// Open mailbox
if (mMessageListFragmentState != null) {
mMessageListFragmentState.restore(mMessageListFragment);
mMessageListFragmentState = null;
}
mMessageListFragment.openMailbox(mMailboxId);
restoreMesasgeListState();
mMailboxListFragment.setSelectedMailbox(mMailboxId);
mTargetActivity.onMailboxChanged(mAccountId, mMailboxId);
mActivity.onMailboxChanged(mAccountId, mMailboxId);
// If a message ID was specified, show it; otherwise show the mailbox list
if (messageId == -1) {
mThreePane.showLeftPane(); // Show mailbox list
mThreePane.showLeftPane();
} else {
selectMessage(messageId);
}
}
/**
* Call it to select a mailbox.
*
* We assume the message passed here belongs to the account/mailbox selected with
* {@link #selectAccount} and {@link #selectMailbox}.
* Select a message to view.
* We assume the message selected here belongs to the mailbox selected with
* {@link #selectMailbox}.
*/
public void selectMessage(long messageId) {
private void selectMessage(long messageId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "selectMessage messageId=" + messageId);
}
@ -452,9 +548,9 @@ class MessageListXLFragmentManager {
return;
}
saveMessageListFragmentState();
mMessageListFragmentState = mMessageListFragment.getState();
// Update member.
// Update member
mMessageId = messageId;
// Open message
@ -463,28 +559,6 @@ class MessageListXLFragmentManager {
mThreePane.showRightPane(); // Show message view
}
/**
* Unselect the currently viewed message, if any, and release the resoruce grabbed by the
* message view.
*
* This must be called when the three pane reports that the message view pane gets hidden.
*/
private void onMessageViewClosed() {
mMessageId = -1;
mMessageListFragment.setSelectedMessage(-1);
mMessageViewFragment.clearContent();
}
private void startInboxLookup() {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "startLookForInbox account=" + mAccountId);
}
closeMailboxFinder();
mMailboxFinder = new MailboxFinder(mContext, mAccountId, Mailbox.TYPE_INBOX,
mMailboxFinderCallback);
mMailboxFinder.startLookup();
}
private void closeMailboxFinder() {
if (mMailboxFinder != null) {
mMailboxFinder.cancel();
@ -492,69 +566,104 @@ class MessageListXLFragmentManager {
}
}
private class MailboxFinderCallback implements MailboxFinder.Callback {
@Override
public void onAccountNotFound() {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MailboxFinderCallback.onAccountNotFound");
}
// Shouldn't happen
}
@Override
public void onAccountSecurityHold(long accountId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MailboxFinderCallback.onAccountSecurityHold");
}
mTargetActivity.onAccountSecurityHold(accountId);
}
@Override
public void onMailboxFound(long accountId, long mailboxId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, " Found inbox");
}
selectMailbox(mailboxId, -1);
}
@Override
public void onMailboxNotFound(long accountId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Logging.LOG_TAG, "MailboxFinderCallback.onMailboxNotFound");
}
// Shouldn't happen
}
}
public void updateMessageCommandButtons(boolean enableMoveToNewer, boolean enableMoveToOlder,
int currentPosition, int countMessages) {
mMessageCommandButtons.enableNavigationButtons(enableMoveToNewer, enableMoveToOlder,
currentPosition, countMessages);
}
private class CommandButtonCallback implements MessageCommandButtonView.Callback {
@Override
public void onMoveToNewer() {
mTargetActivity.onMoveToNewer();
MessageListXLFragmentManager.this.onMoveToNewer();
}
@Override
public void onMoveToOlder() {
mTargetActivity.onMoveToOlder();
MessageListXLFragmentManager.this.onMoveToOlder();
}
}
private class ThreePaneLayoutCallback implements ThreePaneLayout.Callback {
@Override
public void onVisiblePanesChanged(int previousVisiblePanes) {
updateActionBar();
final int visiblePanes = mThreePane.getVisiblePanes();
if (((visiblePanes & ThreePaneLayout.PANE_RIGHT) == 0) &&
((previousVisiblePanes & ThreePaneLayout.PANE_RIGHT) != 0)) {
// Message view just got hidden
onMessageViewClosed();
}
mMessageListFragment.setVisibility((visiblePanes & ThreePaneLayout.PANE_MIDDLE) != 0);
private void onCurrentMessageGone() {
switch (Preferences.getPreferences(mActivity).getAutoAdvanceDirection()) {
case Preferences.AUTO_ADVANCE_NEWER:
if (onMoveToNewer()) return;
if (onMoveToOlder()) return;
break;
case Preferences.AUTO_ADVANCE_OLDER:
if (onMoveToOlder()) return;
if (onMoveToNewer()) return;
break;
}
// Last message in the box or AUTO_ADVANCE_MESSAGE_LIST. Go back to message list.
goBackToMailbox();
}
/**
* Potentially create a new {@link MessageOrderManager}; if it's not already started or if
* the account has changed, and sync it to the current message.
*/
private void updateMessageOrderManager() {
if (!isMailboxSelected()) {
return;
}
final long mailboxId = getMailboxId();
if (mOrderManager == null || mOrderManager.getMailboxId() != mailboxId) {
stopMessageOrderManager();
mOrderManager =
new MessageOrderManager(mActivity, mailboxId, mMessageOrderManagerCallback);
}
if (isMessageSelected()) {
mOrderManager.moveTo(getMessageId());
}
}
private class MessageOrderManagerCallback implements MessageOrderManager.Callback {
@Override
public void onMessagesChanged() {
updateNavigationArrows();
}
@Override
public void onMessageNotFound() {
// Current message gone.
goBackToMailbox();
}
}
/**
* Stop {@link MessageOrderManager}.
*/
private void stopMessageOrderManager() {
if (mOrderManager != null) {
mOrderManager.close();
mOrderManager = null;
}
}
/**
* Disable/enable the move-to-newer/older buttons.
*/
private void updateNavigationArrows() {
if (mOrderManager == null) {
// shouldn't happen, but just in case
mMessageCommandButtons.enableNavigationButtons(false, false, 0, 0);
} else {
mMessageCommandButtons.enableNavigationButtons(
mOrderManager.canMoveToNewer(), mOrderManager.canMoveToOlder(),
mOrderManager.getCurrentPosition(), mOrderManager.getTotalMessageCount());
}
}
private boolean onMoveToOlder() {
if (isMessageSelected() && (mOrderManager != null)
&& mOrderManager.moveToOlder()) {
selectMessage(mOrderManager.getCurrentMessageId());
return true;
}
return false;
}
private boolean onMoveToNewer() {
if (isMessageSelected() && (mOrderManager != null)
&& mOrderManager.moveToNewer()) {
selectMessage(mOrderManager.getCurrentMessageId());
return true;
}
return false;
}
}