diff --git a/res/layout/account_selector.xml b/res/layout/account_selector.xml
deleted file mode 100644
index a546552a4..000000000
--- a/res/layout/account_selector.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
diff --git a/res/layout/action_bar_current_mailbox.xml b/res/layout/action_bar_current_mailbox.xml
deleted file mode 100644
index 5759b3840..000000000
--- a/res/layout/action_bar_current_mailbox.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
diff --git a/res/layout/action_bar_custom_view.xml b/res/layout/action_bar_custom_view.xml
index 609ba824d..c2f412d30 100644
--- a/res/layout/action_bar_custom_view.xml
+++ b/res/layout/action_bar_custom_view.xml
@@ -26,8 +26,8 @@
android:layout_height="0dip"
>
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/account_selector_dropdown.xml b/res/layout/action_bar_spinner_dropdown.xml
similarity index 87%
rename from res/layout/account_selector_dropdown.xml
rename to res/layout/action_bar_spinner_dropdown.xml
index 3c4c79b24..8e9f5bef3 100644
--- a/res/layout/account_selector_dropdown.xml
+++ b/res/layout/action_bar_spinner_dropdown.xml
@@ -17,6 +17,8 @@
@@ -38,14 +39,12 @@
android:id="@+id/display_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:maxWidth="@dimen/account_spinner_dropdown_account_name_max_width"
style="@style/action_bar_account_name"
/>
diff --git a/res/layout/account_selector_dropdown_header.xml b/res/layout/action_bar_spinner_dropdown_header.xml
similarity index 100%
rename from res/layout/account_selector_dropdown_header.xml
rename to res/layout/action_bar_spinner_dropdown_header.xml
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
index a75e8ffe6..29d147eb9 100644
--- a/res/values/dimensions.xml
+++ b/res/values/dimensions.xml
@@ -53,7 +53,8 @@
0dip
0dip
- 352dip
+ 250dip
+ 300dip
14sp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6f4598cc8..0515e6e05 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1153,6 +1153,9 @@ save attachment.
Search %1$s
+
+ Folders
+
Folder check frequency
diff --git a/src/com/android/email/FolderProperties.java b/src/com/android/email/FolderProperties.java
index 9b95404f7..fdcaa8d48 100644
--- a/src/com/android/email/FolderProperties.java
+++ b/src/com/android/email/FolderProperties.java
@@ -71,10 +71,7 @@ public class FolderProperties {
return sInstance;
}
- /**
- * Lookup names of localized special mailboxes
- */
- private String getDisplayName(int type, long mailboxId) {
+ public String getCombinedMailboxName(long mailboxId) {
// Special combined mailboxes
int resId = 0;
@@ -91,13 +88,21 @@ public class FolderProperties {
if (resId != 0) {
return mContext.getString(resId);
}
-
- if (type < mSpecialMailbox.length) {
- return mSpecialMailbox[type];
- }
return null;
}
+ /**
+ * Lookup names of localized special mailboxes
+ */
+ private String getDisplayName(int type, long mailboxId) {
+ String name = getCombinedMailboxName(mailboxId);
+
+ if ((name == null) && (type < mSpecialMailbox.length)) {
+ name = mSpecialMailbox[type];
+ }
+ return name;
+ }
+
/**
* Return the display name for a mailbox for UI. For normal mailboxes, it just returns
* {@code originalDisplayName}, but for special mailboxes (such as combined mailboxes) it
diff --git a/src/com/android/email/activity/AccountSelectorAdapter.java b/src/com/android/email/activity/AccountSelectorAdapter.java
index 60978ebbd..52149fc11 100644
--- a/src/com/android/email/activity/AccountSelectorAdapter.java
+++ b/src/com/android/email/activity/AccountSelectorAdapter.java
@@ -24,12 +24,14 @@ import com.android.email.data.ClosingMatrixCursor;
import com.android.email.data.ThrottlingCursorLoader;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
+import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.utility.Utility;
import java.util.ArrayList;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Loader;
@@ -50,10 +52,16 @@ import android.widget.TextView;
public class AccountSelectorAdapter extends CursorAdapter {
/** meta data column for an message count (unread or total, depending on row) */
private static final String MESSAGE_COUNT = "unreadCount";
+
/** meta data column for the row type; used for display purposes */
private static final String ROW_TYPE = "rowType";
+
/** meta data position of the currently selected account in the drop-down list */
private static final String ACCOUNT_POSITION = "accountPosition";
+
+ /** "account id" virtual column name for the matrix cursor */
+ private static final String ACCOUNT_ID = "accountId";
+
private static final int ROW_TYPE_HEADER = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
@SuppressWarnings("unused")
private static final int ROW_TYPE_MAILBOX = 0;
@@ -77,6 +85,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
Account.EMAIL_ADDRESS,
MESSAGE_COUNT,
ACCOUNT_POSITION,
+ ACCOUNT_ID,
};
/** Sort order. Show the default account first. */
@@ -92,8 +101,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
* @param context a context
* @param accountId the ID of the currently viewed account
*/
- public static Loader createLoader(Context context, long accountId) {
- return new AccountsLoader(context, accountId, UiUtilities.useTwoPane(context));
+ public static Loader createLoader(Context context, long accountId, long mailboxId) {
+ return new AccountsLoader(context, accountId, mailboxId, UiUtilities.useTwoPane(context));
}
public AccountSelectorAdapter(Context context) {
@@ -103,22 +112,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
}
/**
- * Invoked when the action bar needs the view of the text in the bar itself. The default
- * is to show just the display name of the cursor at the given position.
- */
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (!isAccountItem(position)) {
- // asked to show a recent mailbox; instead, show the account associated w/ the mailbox
- int newPosition = getAccountPosition(position);
- if (newPosition != UNKNOWN_POSITION) {
- position = newPosition;
- }
- }
- return super.getView(position, convertView, parent);
- }
-
- /**
+ * {@inheritDoc}
+ *
* The account selector view can contain one of four types of row data:
*
* - headers
@@ -132,26 +127,27 @@ public class AccountSelectorAdapter extends CursorAdapter {
* mailboxes display an unread count; whereas "show all folders" does not. To determine
* if a particular row is "show all folders" verify that a) it's not an account row and
* b) it's ID is {@link Mailbox#NO_MAILBOX}.
+ *
+ * TODO Use recycled views. ({@link #getViewTypeCount} and {@link #getItemViewType})
*/
@Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ public View getView(int position, View convertView, ViewGroup parent) {
Cursor c = getCursor();
c.moveToPosition(position);
-
View view;
if (c.getInt(c.getColumnIndex(ROW_TYPE)) == ROW_TYPE_HEADER) {
- view = mInflater.inflate(R.layout.account_selector_dropdown_header, parent, false);
+ view = mInflater.inflate(R.layout.action_bar_spinner_dropdown_header, parent, false);
final TextView displayNameView = (TextView) view.findViewById(R.id.display_name);
final String displayName = getDisplayName(c);
displayNameView.setText(displayName);
} else {
- view = mInflater.inflate(R.layout.account_selector_dropdown, parent, false);
+ view = mInflater.inflate(R.layout.action_bar_spinner_dropdown, parent, false);
final TextView displayNameView = (TextView) view.findViewById(R.id.display_name);
final TextView emailAddressView = (TextView) view.findViewById(R.id.email_address);
final TextView unreadCountView = (TextView) view.findViewById(R.id.unread_count);
- final String displayName = getDisplayName(position);
- final String emailAddress = getAccountEmailAddress(position);
+ final String displayName = getDisplayName(c);
+ final String emailAddress = getAccountEmailAddress(c);
displayNameView.setText(displayName);
@@ -163,12 +159,12 @@ public class AccountSelectorAdapter extends CursorAdapter {
emailAddressView.setText(emailAddress);
}
- boolean isAccount = isAccountItem(position);
+ boolean isAccount = isAccountItem(c);
long id = getId(c);
if (isAccount || id != Mailbox.NO_MAILBOX) {
unreadCountView.setVisibility(View.VISIBLE);
unreadCountView.setText(UiUtilities.getMessageCountForUi(mContext,
- getAccountUnreadCount(position), true));
+ getAccountUnreadCount(c), true));
} else {
unreadCountView.setVisibility(View.INVISIBLE);
}
@@ -177,14 +173,13 @@ public class AccountSelectorAdapter extends CursorAdapter {
}
@Override
- public void bindView(View view, Context context, Cursor cursor) {
- TextView textView = (TextView) view.findViewById(R.id.display_name);
- textView.setText(getDisplayName(cursor));
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return null; // we don't reuse views. This method never gets called.
}
@Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.account_selector, parent, false);
+ public void bindView(View view, Context context, Cursor cursor) {
+ // we don't reuse views. This method never gets called.
}
@Override
@@ -209,6 +204,10 @@ public class AccountSelectorAdapter extends CursorAdapter {
public boolean isAccountItem(int position) {
Cursor c = getCursor();
c.moveToPosition(position);
+ return isAccountItem(c);
+ }
+
+ public boolean isAccountItem(Cursor c) {
return (c.getLong(c.getColumnIndex(ROW_TYPE)) == ROW_TYPE_ACCOUNT);
}
@@ -218,24 +217,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
return (c.getLong(c.getColumnIndex(ROW_TYPE)) == ROW_TYPE_MAILBOX);
}
- private String getDisplayName(int position) {
- final Cursor c = getCursor();
- return c.moveToPosition(position) ? getDisplayName(c) : null;
- }
-
- private String getAccountEmailAddress(int position) {
- final Cursor c = getCursor();
- return c.moveToPosition(position) ? getAccountEmailAddress(c) : null;
- }
-
- private int getAccountUnreadCount(int position) {
- final Cursor c = getCursor();
- return c.moveToPosition(position) ? getMessageCount(c) : 0;
- }
-
- int getAccountPosition(int position) {
- final Cursor c = getCursor();
- return c.moveToPosition(position) ? getAccountPosition(c) : UNKNOWN_POSITION;
+ private int getAccountUnreadCount(Cursor c) {
+ return getMessageCount(c);
}
/**
@@ -245,6 +228,24 @@ public class AccountSelectorAdapter extends CursorAdapter {
return c.getLong(c.getColumnIndex(EmailContent.RECORD_ID));
}
+ /**
+ * @return ID of the account / mailbox for a row
+ */
+ public long getId(int position) {
+ final Cursor c = getCursor();
+ return c.moveToPosition(position) ? getId(c) : Account.NO_ACCOUNT;
+ }
+
+ /**
+ * @return ID of the account for a row
+ */
+ public long getAccountId(int position) {
+ final Cursor c = getCursor();
+ return c.moveToPosition(position)
+ ? c.getLong(c.getColumnIndex(ACCOUNT_ID))
+ : Account.NO_ACCOUNT;
+ }
+
/** Returns the account name extracted from the given cursor. */
static String getDisplayName(Cursor cursor) {
return cursor.getString(cursor.getColumnIndex(Account.DISPLAY_NAME));
@@ -263,9 +264,13 @@ public class AccountSelectorAdapter extends CursorAdapter {
return cursor.getInt(cursor.getColumnIndex(MESSAGE_COUNT));
}
- /** Returns the account position extracted from the given cursor. */
- private static int getAccountPosition(Cursor cursor) {
- return cursor.getInt(cursor.getColumnIndex(ACCOUNT_POSITION));
+ private static String sCombinedViewDisplayName;
+ private static String getCombinedViewDisplayName(Context c) {
+ if (sCombinedViewDisplayName == null) {
+ sCombinedViewDisplayName = c.getResources().getString(
+ R.string.mailbox_list_account_selector_combined_view);
+ }
+ return sCombinedViewDisplayName;
}
/**
@@ -278,16 +283,18 @@ public class AccountSelectorAdapter extends CursorAdapter {
static class AccountsLoader extends ThrottlingCursorLoader {
private final Context mContext;
private final long mAccountId;
+ private final long mMailboxId;
private final boolean mUseTwoPane; // Injectable for test
private final FolderProperties mFolderProperties;
@VisibleForTesting
- AccountsLoader(Context context, long accountId, boolean useTwoPane) {
+ AccountsLoader(Context context, long accountId, long mailboxId, boolean useTwoPane) {
// Super class loads a regular account cursor, but we replace it in loadInBackground().
super(context, Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null,
ORDER_BY);
mContext = context;
mAccountId = accountId;
+ mMailboxId = mailboxId;
mFolderProperties = FolderProperties.getInstance(mContext);
mUseTwoPane = useTwoPane;
}
@@ -300,17 +307,19 @@ public class AccountSelectorAdapter extends CursorAdapter {
= new CursorWithExtras(ADAPTER_PROJECTION, accountsCursor);
final int accountPosition = addAccountsToCursor(resultCursor, accountsCursor);
addRecentsToCursor(resultCursor, accountPosition);
- return Utility.CloseTraceCursorWrapper.get(resultCursor);
+
+ resultCursor.setAccountMailboxInfo(getContext(), mAccountId, mMailboxId);
+ return resultCursor;
}
/** Adds the account list [with extra meta data] to the given matrix cursor */
private int addAccountsToCursor(CursorWithExtras matrixCursor, Cursor accountCursor) {
int accountPosition = UNKNOWN_POSITION;
accountCursor.moveToPosition(-1);
+
// Add a header for the accounts
- String header =
- mContext.getString(R.string.mailbox_list_account_selector_account_header);
- addRow(matrixCursor, ROW_TYPE_HEADER, 0L, header, null, 0, UNKNOWN_POSITION);
+ addHeaderRow(matrixCursor, mContext.getString(
+ R.string.mailbox_list_account_selector_account_header));
matrixCursor.mAccountCount = accountCursor.getCount();
int totalUnread = 0;
@@ -323,7 +332,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
final String name = getDisplayName(accountCursor);
final String emailAddress = getAccountEmailAddress(accountCursor);
addRow(matrixCursor, ROW_TYPE_ACCOUNT, accountId, name, emailAddress, unread,
- UNKNOWN_POSITION);
+ UNKNOWN_POSITION, accountId);
totalUnread += unread;
if (accountId == mAccountId) {
accountPosition = currentPosition;
@@ -333,12 +342,12 @@ public class AccountSelectorAdapter extends CursorAdapter {
// Add "combined view" if more than one account exists
final int countAccounts = accountCursor.getCount();
if (countAccounts > 1) {
- final String name = mContext.getResources().getString(
- R.string.mailbox_list_account_selector_combined_view);
final String accountCount = mContext.getResources().getQuantityString(
R.plurals.number_of_accounts, countAccounts, countAccounts);
addRow(matrixCursor, ROW_TYPE_ACCOUNT, Account.ACCOUNT_ID_COMBINED_VIEW,
- name, accountCount, totalUnread, UNKNOWN_POSITION);
+ getCombinedViewDisplayName(mContext),
+ accountCount, totalUnread, UNKNOWN_POSITION,
+ Account.ACCOUNT_ID_COMBINED_VIEW);
// Increment the account count for the combined account.
matrixCursor.mAccountCount++;
@@ -373,9 +382,8 @@ public class AccountSelectorAdapter extends CursorAdapter {
if (!mUseTwoPane) {
// "Recent mailboxes" header
- String mailboxHeader = mContext.getString(
- R.string.mailbox_list_account_selector_mailbox_header_fmt, emailAddress);
- addRow(matrixCursor, ROW_TYPE_HEADER, 0L, mailboxHeader, null, 0, UNKNOWN_POSITION);
+ addHeaderRow(matrixCursor, mContext.getString(
+ R.string.mailbox_list_account_selector_mailbox_header_fmt, emailAddress));
}
if (recentCount > 0) {
@@ -389,7 +397,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
String name = mContext.getString(
R.string.mailbox_list_account_selector_show_all_folders);
addRow(matrixCursor, ROW_TYPE_MAILBOX, Mailbox.NO_MAILBOX, name, null, 0,
- accountPosition);
+ accountPosition, mAccountId);
}
}
@@ -408,33 +416,114 @@ public class AccountSelectorAdapter extends CursorAdapter {
}
addRow(matrixCursor, ROW_TYPE_MAILBOX, mailboxId,
mFolderProperties.getDisplayName(c), null,
- mFolderProperties.getMessageCount(c), accountPosition);
+ mFolderProperties.getMessageCount(c), accountPosition, mAccountId);
+ }
+
+ private void addHeaderRow(MatrixCursor cursor, String name) {
+ addRow(cursor, ROW_TYPE_HEADER, 0L, name, null, 0, UNKNOWN_POSITION,
+ Account.NO_ACCOUNT);
}
/** Adds a row to the given cursor */
private void addRow(MatrixCursor cursor, int rowType, long id, String name,
- String emailAddress, int messageCount, int listPosition) {
+ String emailAddress, int messageCount, int listPosition, long accountId) {
cursor.newRow()
.add(rowType)
.add(id)
.add(name)
.add(emailAddress)
.add(messageCount)
- .add(listPosition);
+ .add(listPosition)
+ .add(accountId);
}
}
/** Cursor with some extra meta data. */
static class CursorWithExtras extends ClosingMatrixCursor {
+
/** Number of account elements, including the combined account row. */
private int mAccountCount;
/** Number of recent mailbox elements */
private int mRecentCount;
+ private boolean mAccountExists;
+
+ /**
+ * Account ID that's loaded.
+ */
+ private long mAccountId;
+ private String mAccountDisplayName;
+
+ /**
+ * Mailbox ID that's loaded.
+ */
+ private long mMailboxId;
+ private String mMailboxDisplayName;
+ private int mMailboxMessageCount;
+
private CursorWithExtras(String[] columnNames, Cursor innerCursor) {
super(columnNames, innerCursor);
}
+ private static final String[] ACCOUNT_INFO_PROJECTION = new String[] {
+ AccountColumns.DISPLAY_NAME,
+ };
+ private static final String[] MAILBOX_INFO_PROJECTION = new String[] {
+ MailboxColumns.ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
+ MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT
+ };
+
+ /**
+ * Set the current account/mailbox info.
+ */
+ private void setAccountMailboxInfo(Context context, long accountId, long mailboxId) {
+ mAccountId = accountId;
+ mMailboxId = mailboxId;
+
+ // Get account info
+ if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
+ // We need to treat ACCOUNT_ID_COMBINED_VIEW specially...
+ mAccountExists = true;
+ mAccountDisplayName = getCombinedViewDisplayName(context);
+ mMailboxDisplayName = FolderProperties.getInstance(context)
+ .getCombinedMailboxName(mMailboxId);
+
+ // TODO Would be nicer to show message count for combined mailboxes too..
+ mMailboxMessageCount = 0;
+ return;
+ }
+
+ mAccountDisplayName = Utility.getFirstRowString(context,
+ ContentUris.withAppendedId(Account.CONTENT_URI, accountId),
+ ACCOUNT_INFO_PROJECTION, null, null, null, 0, null);
+ if (mAccountDisplayName == null) {
+ // Account gone!
+ mAccountExists = false;
+ return;
+ }
+ mAccountExists = true;
+
+ // If mailbox not specified, done.
+ if (mMailboxId == Mailbox.NO_MAILBOX) {
+ return;
+ }
+
+ // Get mailbox info
+ final ContentResolver r = context.getContentResolver();
+ final Cursor mailboxCursor = r.query(
+ ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
+ MAILBOX_INFO_PROJECTION, null, null, null);
+ try {
+ if (mailboxCursor.moveToFirst()) {
+ final FolderProperties fp = FolderProperties.getInstance(context);
+ mMailboxDisplayName = fp.getDisplayName(mailboxCursor);
+ mMailboxMessageCount = fp.getMessageCount(mailboxCursor);
+ }
+ } finally {
+ mailboxCursor.close();
+ }
+ }
+
/**
* Returns the cursor position of the item with the given ID. Or {@link #UNKNOWN_POSITION}
* if the given ID does not exist.
@@ -456,5 +545,32 @@ public class AccountSelectorAdapter extends CursorAdapter {
public int getRecentMailboxCount() {
return mRecentCount;
}
+
+ public long getAccountId() {
+ return mAccountId;
+ }
+
+ public String getAccountDisplayName() {
+ return mAccountDisplayName;
+ }
+
+ public long getMailboxId() {
+ return mMailboxId;
+ }
+
+ public String getMailboxDisplayName() {
+ return mMailboxDisplayName;
+ }
+
+ public int getMailboxMessageCount() {
+ return mMailboxMessageCount;
+ }
+
+ /**
+ * @return {@code true} if the specified accuont exists.
+ */
+ public boolean accountExists() {
+ return mAccountExists;
+ }
}
}
diff --git a/src/com/android/email/activity/ActionBarController.java b/src/com/android/email/activity/ActionBarController.java
index 2a3997388..0ff830680 100644
--- a/src/com/android/email/activity/ActionBarController.java
+++ b/src/com/android/email/activity/ActionBarController.java
@@ -16,30 +16,29 @@
package com.android.email.activity;
+import com.android.email.R;
+import com.android.emailcommon.provider.Account;
+import com.android.emailcommon.provider.Mailbox;
+import com.android.emailcommon.utility.Utility;
+
import android.app.ActionBar;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
-import android.content.ContentUris;
import android.content.Context;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
+import android.os.Handler;
import android.text.TextUtils;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ListPopupWindow;
+import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;
-import com.android.email.FolderProperties;
-import com.android.email.R;
-import com.android.email.data.ThrottlingCursorLoader;
-import com.android.emailcommon.Logging;
-import com.android.emailcommon.provider.Account;
-import com.android.emailcommon.provider.EmailContent;
-import com.android.emailcommon.provider.EmailContent.MailboxColumns;
-import com.android.emailcommon.provider.Mailbox;
-
/**
* Manages the account name and the custom view part on the action bar.
*
@@ -68,25 +67,29 @@ public class ActionBarController {
private static final int LOADER_ID_ACCOUNT_LIST
= EmailActivity.ACTION_BAR_CONTROLLER_LOADER_ID_BASE + 0;
- private static final int LOADER_ID_MAILBOX
- = EmailActivity.ACTION_BAR_CONTROLLER_LOADER_ID_BASE + 1;
private final Context mContext;
private final LoaderManager mLoaderManager;
private final ActionBar mActionBar;
+ /** "Folders" label shown with account name on 1-pane mailbox list */
+ private final String mAllFoldersLabel;
+
private final View mActionBarCustomView;
- private final View mMailboxNameContainer;
- private final TextView mMailboxNameView;
- private final TextView mUnreadCountView;
+ private final View mAccountSpinner;
+ private final TextView mAccountSpinnerLine1View;
+ private final TextView mAccountSpinnerLine2View;
+ private final TextView mAccountSpinnerCountView;
+
private final View mSearchContainer;
private final SearchView mSearchView;
- private final ActionBarNavigationCallback mActionBarNavigationCallback =
- new ActionBarNavigationCallback();
+ private final AccountDropdownPopup mAccountDropdown;
private final AccountSelectorAdapter mAccountsSelectorAdapter;
- private AccountSelectorAdapter.CursorWithExtras mAccountCursor;
+
+ private AccountSelectorAdapter.CursorWithExtras mCursor;
+
/** The current account ID; used to determine if the account has changed. */
private long mLastAccountIdForDirtyCheck = Account.NO_ACCOUNT;
@@ -103,6 +106,20 @@ public class ActionBarController {
}
public interface Callback {
+ /** Values for {@link #getTitleMode}. Show only account name */
+ public static final int TITLE_MODE_ACCOUNT_NAME_ONLY = 0;
+ /** Show the current account name with "Folders" */
+ public static final int TITLE_MODE_ACCOUNT_WITH_ALL_FOLDERS_LABEL = 1;
+ /** Show the current account name and the current mailbox name */
+ public static final int TITLE_MODE_ACCOUNT_WITH_MAILBOX = 2;
+ /**
+ * Show the current message subject. Actual subject is obtained via
+ * {@link #getMessageSubject()}.
+ *
+ * NOT IMPLEMENTED YET
+ */
+ public static final int TITLE_MODE_MESSAGE_SUBJECT = 3;
+
/** @return true if an account is selected. */
public boolean isAccountSelected();
@@ -118,8 +135,13 @@ public class ActionBarController {
*/
public long getMailboxId();
- /** @return true if the current mailbox name should be shown. */
- public boolean shouldShowMailboxName();
+ /**
+ * @return constants such as {@link #TITLE_MODE_ACCOUNT_NAME_ONLY}.
+ */
+ public int getTitleMode();
+
+ /** @see #TITLE_MODE_MESSAGE_SUBJECT */
+ public String getMessageSubject();
/** @return the "UP" arrow should be shown. */
public boolean shouldShowUp();
@@ -132,10 +154,12 @@ public class ActionBarController {
/**
* Invoked when a recent mailbox is selected on the account spinner.
+ *
+ * @param accountId ID of the selected account, or {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
* @param mailboxId The ID of the selected mailbox, or {@link Mailbox#NO_MAILBOX} if the
* special option "show all mailboxes" was selected.
*/
- public void onMailboxSelected(long mailboxId);
+ public void onMailboxSelected(long accountId, long mailboxId);
/** Called when no accounts are found in the database. */
public void onNoAccountsFound();
@@ -159,42 +183,58 @@ public class ActionBarController {
mLoaderManager = loaderManager;
mActionBar = actionBar;
mCallback = callback;
+ mAllFoldersLabel = mContext.getResources().getString(
+ R.string.action_bar_mailbox_list_title);
mAccountsSelectorAdapter = new AccountSelectorAdapter(mContext);
- mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE
- | ActionBar.DISPLAY_SHOW_HOME
- | ActionBar.DISPLAY_SHOW_CUSTOM);
+ // Configure action bar.
+ mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_CUSTOM);
// Prepare the custom view
final LayoutInflater inflater = LayoutInflater.from(mContext);
mActionBarCustomView = inflater.inflate(R.layout.action_bar_custom_view, null);
final ActionBar.LayoutParams customViewLayout = new ActionBar.LayoutParams(
- ActionBar.LayoutParams.MATCH_PARENT,
+ ActionBar.LayoutParams.WRAP_CONTENT,
ActionBar.LayoutParams.MATCH_PARENT);
- customViewLayout.setMargins(0 , 0, 0, 0);
+ customViewLayout.setMargins(0, 0, 0, 0);
mActionBar.setCustomView(mActionBarCustomView, customViewLayout);
- // Mailbox name / unread count
- mMailboxNameContainer = UiUtilities.getView(mActionBarCustomView,
- R.id.current_mailbox_container);
- mMailboxNameView = UiUtilities.getView(mMailboxNameContainer, R.id.mailbox_name);
- mUnreadCountView = UiUtilities.getView(mMailboxNameContainer, R.id.unread_count);
+ // Account spinner
+ mAccountSpinner = UiUtilities.getView(mActionBarCustomView, R.id.account_spinner);
+
+ mAccountSpinnerLine1View = UiUtilities.getView(mActionBarCustomView, R.id.spinner_line_1);
+ mAccountSpinnerLine2View = UiUtilities.getView(mActionBarCustomView, R.id.spinner_line_2);
+ mAccountSpinnerCountView = UiUtilities.getView(mActionBarCustomView, R.id.spinner_count);
// Search
mSearchContainer = UiUtilities.getView(mActionBarCustomView, R.id.search_container);
mSearchView = UiUtilities.getView(mSearchContainer, R.id.search_view);
mSearchView.setSubmitButtonEnabled(true);
mSearchView.setOnQueryTextListener(mOnQueryText);
+
+ // Account dropdown
+ mAccountDropdown = new AccountDropdownPopup(mContext);
+ mAccountDropdown.setAdapter(mAccountsSelectorAdapter);
+
+ mAccountSpinner.setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) {
+ if (mAccountsSelectorAdapter.getCount() > 0) {
+ mAccountDropdown.show();
+ }
+ }
+ });
}
/** Must be called from {@link UIControllerBase#onActivityCreated()} */
public void onActivityCreated() {
- loadAccounts();
refresh();
}
/** Must be called from {@link UIControllerBase#onActivityDestroy()} */
public void onActivityDestroy() {
+ if (mAccountDropdown.isShowing()) {
+ mAccountDropdown.dismiss();
+ }
}
/** Must be called from {@link UIControllerBase#onSaveInstanceState} */
@@ -234,11 +274,6 @@ public class ActionBarController {
}
mSearchMode = MODE_SEARCH;
- // Need to force it to mode "standard" to hide it.
- mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- mActionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
- mSearchContainer.setVisibility(View.VISIBLE);
-
// Focus on the search input box and throw up the IME if specified.
// TODO: HACK. this is a workaround IME not popping up.
mSearchView.setIconified(false);
@@ -251,11 +286,6 @@ public class ActionBarController {
return;
}
mSearchMode = MODE_NORMAL;
- mSearchContainer.setVisibility(View.GONE);
- mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
-
- // Force update of account list when we exit search.
- updateAccountList();
refresh();
mCallback.onSearchExit();
@@ -277,187 +307,141 @@ public class ActionBarController {
/** Refreshes the action bar display. */
public void refresh() {
+ // The actual work is in refreshInernal(), but we don't call it directly here, because:
+ // 1. refresh() is called very often.
+ // 2. to avoid nested fragment transaction.
+ // refresh is often called during a fragment transaction, but updateTitle() may call
+ // a callback which would initiate another fragment transaction.
+ final Handler h = Utility.getMainThreadHandler();
+ h.removeCallbacks(mRefreshRunnable);
+ h.post(mRefreshRunnable);
+ }
+
+ private final Runnable mRefreshRunnable = new Runnable() {
+ @Override public void run() {
+ refreshInernal();
+ }
+ };
+ private void refreshInernal() {
final boolean showUp = isInSearchMode() || mCallback.shouldShowUp();
mActionBar.setDisplayOptions(showUp
? ActionBar.DISPLAY_HOME_AS_UP : 0, ActionBar.DISPLAY_HOME_AS_UP);
- if (isInSearchMode()) {
- mMailboxNameContainer.setVisibility(View.GONE);
- } else {
- mMailboxNameContainer.setVisibility(mCallback.shouldShowMailboxName()
- ? View.VISIBLE : View.GONE);
- }
-
- // Update the account list only when the account has changed.
- if (mLastAccountIdForDirtyCheck != mCallback.getUIAccountId()) {
- mLastAccountIdForDirtyCheck = mCallback.getUIAccountId();
- // If the selected account changes, reload the cursor to update the recent mailboxes
- if (mLastAccountIdForDirtyCheck != Account.NO_ACCOUNT) {
- mLoaderManager.destroyLoader(LOADER_ID_ACCOUNT_LIST);
- loadAccounts();
- } else {
- updateAccountList();
- }
- }
-
- // Update current mailbox info
+ final long accountId = mCallback.getUIAccountId();
final long mailboxId = mCallback.getMailboxId();
- if (mailboxId == Mailbox.NO_MAILBOX) {
- clearMailboxInfo();
- } else {
- if (mLastMailboxIdForDirtyCheck != mailboxId) {
- mLastMailboxIdForDirtyCheck = mailboxId;
- loadMailboxInfo(mailboxId);
+ if ((mLastAccountIdForDirtyCheck != accountId)
+ || (mLastMailboxIdForDirtyCheck != mailboxId)) {
+ mLastAccountIdForDirtyCheck = accountId;
+ mLastMailboxIdForDirtyCheck = mailboxId;
+
+ if (accountId != Account.NO_ACCOUNT) {
+ loadAccountMailboxInfo(accountId, mailboxId);
}
}
+
+ updateTitle();
}
/**
- * Load account cursor, and update the action bar.
+ * Load account/mailbox info, and account/recent mailbox list.
*/
- private void loadAccounts() {
- mLoaderManager.initLoader(LOADER_ID_ACCOUNT_LIST, null,
+ private void loadAccountMailboxInfo(final long accountId, final long mailboxId) {
+ mLoaderManager.restartLoader(LOADER_ID_ACCOUNT_LIST, null,
new LoaderCallbacks() {
@Override
public Loader onCreateLoader(int id, Bundle args) {
- return AccountSelectorAdapter.createLoader(mContext, mCallback.getUIAccountId());
+ return AccountSelectorAdapter.createLoader(mContext, accountId, mailboxId);
}
@Override
public void onLoadFinished(Loader loader, Cursor data) {
- mAccountCursor = (AccountSelectorAdapter.CursorWithExtras) data;
- updateAccountList();
+ mCursor = (AccountSelectorAdapter.CursorWithExtras) data;
+ updateTitle();
}
@Override
public void onLoaderReset(Loader loader) {
- mAccountCursor = null;
- updateAccountList();
+ mCursor = null;
+ updateTitle();
}
});
}
/**
- * Called when the LOADER_ID_ACCOUNT_LIST loader loads the data. Update the account spinner
- * on the action bar.
+ * Update the "title" part.
*/
- private void updateAccountList() {
- mAccountsSelectorAdapter.swapCursor(mAccountCursor);
+ private void updateTitle() {
+ mAccountsSelectorAdapter.swapCursor(mCursor);
- if (mSearchMode == MODE_SEARCH) {
- // In search mode, so we don't care about the account list - it'll get updated when
- // it goes visible again.
+ if (mCursor == null) {
+ // Initial load not finished.
+ mActionBarCustomView.setVisibility(View.GONE);
return;
}
+ mActionBarCustomView.setVisibility(View.VISIBLE);
- final ActionBar ab = mActionBar;
- if (mAccountCursor == null) {
- // Cursor not ready or closed.
- ab.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
- ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- return;
- }
-
- final int count = mAccountCursor.getAccountCount() + mAccountCursor.getRecentMailboxCount();
- if (count == 0) {
+ if (mCursor.getAccountCount() == 0) {
mCallback.onNoAccountsFound();
return;
}
- // If only one account, don't show the drop down.
- int selectedPosition = mAccountCursor.getPosition(mCallback.getUIAccountId());
- if (count == 1) {
- // Show the account name as the title.
- ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
- ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- if (selectedPosition >= 0) {
- mAccountCursor.moveToPosition(selectedPosition);
- ab.setTitle(AccountSelectorAdapter.getDisplayName(mAccountCursor));
- }
+ if ((mCursor.getAccountId() != Account.NO_ACCOUNT) && !mCursor.accountExists()) {
+ // Accoutn specified, but not exists. Switch to the default account.
+ mCallback.onAccountSelected(Account.getDefaultAccountId(mContext));
+
+ // STOPSHIP If in search mode, we should close the activity. Probably
+ // we should jsut call onSearchExit() instead?
return;
}
- // Update the drop down list.
- if (ab.getNavigationMode() != ActionBar.NAVIGATION_MODE_LIST) {
- ab.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
- ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- ab.setListNavigationCallbacks(mAccountsSelectorAdapter, mActionBarNavigationCallback);
+ if (mSearchMode == MODE_SEARCH) {
+ // In search mode, so we don't care about the account list - it'll get updated when
+ // it goes visible again.
+ mAccountSpinner.setVisibility(View.GONE);
+ mSearchContainer.setVisibility(View.VISIBLE);
+ return;
}
- // Find the currently selected account, and select it.
- if (selectedPosition >= 0) {
- ab.setSelectedNavigationItem(selectedPosition);
+
+ final int mTitleMode = mCallback.getTitleMode();
+
+ // TODO Handle TITLE_MODE_MESSAGE_SUBJECT
+
+ // Account spinner visible.
+ mAccountSpinner.setVisibility(View.VISIBLE);
+ mSearchContainer.setVisibility(View.GONE);
+
+ // Get mailbox name
+ final String mailboxName;
+ if (mTitleMode == Callback.TITLE_MODE_ACCOUNT_WITH_ALL_FOLDERS_LABEL) {
+ mailboxName = mAllFoldersLabel;
+ } else if (mTitleMode == Callback.TITLE_MODE_ACCOUNT_WITH_MAILBOX) {
+ mailboxName = mCursor.getMailboxDisplayName();
+ } else {
+ mailboxName = null;
}
- }
- private class ActionBarNavigationCallback implements ActionBar.OnNavigationListener {
- @Override
- public boolean onNavigationItemSelected(int itemPosition, long itemId) {
- if (mAccountsSelectorAdapter.isAccountItem(itemPosition)
- && itemId != mCallback.getUIAccountId()) {
- mCallback.onAccountSelected(itemId);
- } else if (mAccountsSelectorAdapter.isMailboxItem(itemPosition)) {
- mCallback.onMailboxSelected(itemId);
- // We need to update the selection, otherwise the user is unable to select the
- // recent folder a second time w/o first selecting another item in the spinner
- int selectedPosition = mAccountsSelectorAdapter.getAccountPosition(itemPosition);
- if (selectedPosition != AccountSelectorAdapter.UNKNOWN_POSITION) {
- mActionBar.setSelectedNavigationItem(selectedPosition);
- }
- } else {
- Log.i(Logging.LOG_TAG,
- "Invalid type selected in ActionBarController at index " + itemPosition);
- }
- return true;
+ if (TextUtils.isEmpty(mailboxName)) {
+ mAccountSpinnerLine1View.setText(mCursor.getAccountDisplayName());
+
+ // Only here we change the visibility of line 2, so line 1 will be vertically-centered.
+ mAccountSpinnerLine2View.setVisibility(View.GONE);
+ } else {
+ mAccountSpinnerLine1View.setText(mailboxName);
+ mAccountSpinnerLine2View.setVisibility(View.VISIBLE); // Make sure it's visible again.
+ mAccountSpinnerLine2View.setText(mCursor.getAccountDisplayName());
}
- }
+ mAccountSpinnerCountView.setText(UiUtilities.getMessageCountForUi(
+ mContext, mCursor.getMailboxMessageCount(), true));
- private static final String[] MAILBOX_NAME_COUNT_PROJECTION = new String[] {
- MailboxColumns.ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
- MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT
- };
+ boolean spinnerEnabled = (mCursor.getAccountCount() + mCursor.getRecentMailboxCount()) > 1;
- private void loadMailboxInfo(final long mailboxId) {
- clearMailboxInfo();
- if (mailboxId < 0) {
- // TODO FIXME
- return; // Can't get combined mailbox name with this
+ if (spinnerEnabled) {
+ mAccountSpinner.setClickable(true);
+ } else {
+ mAccountSpinner.setClickable(false);
+ // TODO There's nothing to select -- we should remove the spinner triangle.
+ // (The small triangle shown at the right bottom corner)
}
- mLoaderManager.restartLoader(LOADER_ID_MAILBOX, null,
- new LoaderCallbacks() {
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- return new ThrottlingCursorLoader(mContext,
- ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
- MAILBOX_NAME_COUNT_PROJECTION, null, null, null);
- }
-
- @Override
- public void onLoadFinished(Loader loader, Cursor cursor) {
- if (!cursor.moveToFirst()) {
- clearMailboxInfo();
- return;
- }
- // Update action bar
- FolderProperties fp = FolderProperties.getInstance(mContext);
- updateMailboxInfo(
- fp.getDisplayName(cursor),
- fp.getMessageCount(cursor)
- );
- }
-
- @Override
- public void onLoaderReset(Loader loader) {
- }
- });
- }
-
- private void clearMailboxInfo() {
- updateMailboxInfo("", 0);
- }
-
- private void updateMailboxInfo(String mailboxName, int count) {
- mMailboxNameView.setText(mailboxName);
- mUnreadCountView.setText(UiUtilities.getMessageCountForUi(mContext, count, true));
}
private final SearchView.OnQueryTextListener mOnQueryText
@@ -475,4 +459,44 @@ public class ActionBarController {
}
};
+ private void onAccountSpinnerItemClicked(int position) {
+ if (mAccountsSelectorAdapter == null) { // just in case...
+ return;
+ }
+ final long accountId = mAccountsSelectorAdapter.getAccountId(position);
+
+ if (mAccountsSelectorAdapter.isAccountItem(position)) {
+ mCallback.onAccountSelected(accountId);
+ } else if (mAccountsSelectorAdapter.isMailboxItem(position)) {
+ mCallback.onMailboxSelected(accountId,
+ mAccountsSelectorAdapter.getId(position));
+ }
+ }
+
+ // Based on Spinner.DropdownPopup
+ private class AccountDropdownPopup extends ListPopupWindow {
+ public AccountDropdownPopup(Context context) {
+ super(context);
+
+ setAnchorView(mAccountSpinner);
+ setModal(true);
+ setPromptPosition(POSITION_PROMPT_ABOVE);
+ setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView> parent, View v, int position, long id) {
+ onAccountSpinnerItemClicked(position);
+ dismiss();
+ }
+ });
+ }
+
+ @Override
+ public void show() {
+ setWidth(mContext.getResources().getDimensionPixelSize(
+ R.dimen.account_spinner_dropdown_width));
+ setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
+ super.show();
+ // List view is instantiated in super.show(), so we need to do this after...
+ getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ }
+ }
}
diff --git a/src/com/android/email/activity/MailboxListFragment.java b/src/com/android/email/activity/MailboxListFragment.java
index ff50afb0e..08522a150 100644
--- a/src/com/android/email/activity/MailboxListFragment.java
+++ b/src/com/android/email/activity/MailboxListFragment.java
@@ -190,6 +190,11 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
private long mParentMailboxId;
private long mHighlightedMailboxId;
+ /**
+ * Becomes {@code true} once we determine which mailbox to use as the parent.
+ */
+ private boolean mParentDetermined;
+
/**
* ID of the mailbox that should be highlighted when the next cursor is loaded.
*/
@@ -551,7 +556,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
/**
* @return {@code true} if top-level mailboxes are shown. {@code false} otherwise.
*/
- public boolean isRoot() {
+ private boolean isRoot() {
return mParentMailboxId == Mailbox.NO_MAILBOX;
}
@@ -580,6 +585,19 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
return true;
}
+ /**
+ * @return {@code true} if the fragment is showing nested mailboxes and we can go one level up.
+ * {@code false} otherwise, meaning we're showing the top level mailboxes *OR*
+ * we're still loading initial data and we can't determine if we're going to show
+ * top-level or not.
+ */
+ public boolean canNavigateUp() {
+ if (!mParentDetermined) {
+ return false; // We can't determine yet...
+ }
+ return !isRoot();
+ }
+
/**
* A task to determine what parent mailbox ID/highlighted mailbox ID to use for the "UP"
* navigation, given the current parent mailbox ID, the highlighted mailbox ID, and {@link
@@ -781,6 +799,8 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
mListAdapter.swapCursor(null);
setListShown(false);
} else {
+ mParentDetermined = true; // Okay now we're sure which mailbox is the parent.
+
mListAdapter.swapCursor(cursor);
setListShown(true);
diff --git a/src/com/android/email/activity/UIControllerBase.java b/src/com/android/email/activity/UIControllerBase.java
index 121cd4cf1..24633ccdd 100644
--- a/src/com/android/email/activity/UIControllerBase.java
+++ b/src/com/android/email/activity/UIControllerBase.java
@@ -431,12 +431,12 @@ abstract class UIControllerBase implements MailboxListFragment.Callback,
/**
* Show the default view for the given account.
*
- * No-op if the given account is already selected.
- *
* @param accountId ID of the account to load. Can be {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
* Must never be {@link Account#NO_ACCOUNT}.
+ * @param forceShowInbox If {@code false} and the given account is already selected, do nothing.
+ * If {@code false}, we always change the view even if the account is selected.
*/
- public final void switchAccount(long accountId) {
+ public final void switchAccount(long accountId, boolean forceShowInbox) {
if (Account.isSecurityHold(mActivity, accountId)) {
ActivityHelper.showSecurityHoldDialog(mActivity, accountId);
@@ -444,7 +444,7 @@ abstract class UIControllerBase implements MailboxListFragment.Callback,
return;
}
- if (accountId == getUIAccountId()) {
+ if (accountId == getUIAccountId() && !forceShowInbox) {
// Do nothing if the account is already selected. Not even going back to the inbox.
return;
}
diff --git a/src/com/android/email/activity/UIControllerOnePane.java b/src/com/android/email/activity/UIControllerOnePane.java
index dd564a340..11cfcfe88 100644
--- a/src/com/android/email/activity/UIControllerOnePane.java
+++ b/src/com/android/email/activity/UIControllerOnePane.java
@@ -55,7 +55,9 @@ class UIControllerOnePane extends UIControllerBase {
// MailboxListFragment.Callback
@Override
public void onAccountSelected(long accountId) {
- switchAccount(accountId);
+ // It's from combined view, so "forceShowInbox" doesn't really matter.
+ // (We're always switching accounts.)
+ switchAccount(accountId, true);
}
// MailboxListFragment.Callback
@@ -94,7 +96,7 @@ class UIControllerOnePane extends UIControllerBase {
// MessageListFragment.Callback
@Override
public void onMailboxNotFound() {
- switchAccount(getUIAccountId());
+ switchAccount(getUIAccountId(), true);
}
// MessageListFragment.Callback
@@ -202,15 +204,26 @@ class UIControllerOnePane extends UIControllerBase {
// This is all temporary as we'll have a different action bar controller for 1-pane.
private class ActionBarControllerCallback implements ActionBarController.Callback {
@Override
- public boolean shouldShowMailboxName() {
- return false; // no mailbox name/unread count.
+ public int getTitleMode() {
+ if (isMailboxListInstalled()) {
+ return TITLE_MODE_ACCOUNT_WITH_ALL_FOLDERS_LABEL;
+ }
+ // TODO Return TITLE_MODE_MESSAGE_SUBJECT if isMessageViewInstalled()
+ return TITLE_MODE_ACCOUNT_WITH_MAILBOX;
}
+ public String getMessageSubject() {
+ if (isMessageViewInstalled()) {
+ return "TODO: Return current message subject here";
+ } else {
+ return null;
+ }
+ }
@Override
public boolean shouldShowUp() {
return isMessageViewInstalled()
- || (isMailboxListInstalled() && !getMailboxListFragment().isRoot());
+ || (isMailboxListInstalled() && getMailboxListFragment().canNavigateUp());
}
@Override
@@ -224,11 +237,11 @@ class UIControllerOnePane extends UIControllerBase {
}
@Override
- public void onMailboxSelected(long mailboxId) {
+ public void onMailboxSelected(long accountId, long mailboxId) {
if (mailboxId == Mailbox.NO_MAILBOX) {
showAllMailboxes();
} else {
- openMailbox(getUIAccountId(), mailboxId);
+ openMailbox(accountId, mailboxId);
}
}
@@ -239,7 +252,7 @@ class UIControllerOnePane extends UIControllerBase {
@Override
public void onAccountSelected(long accountId) {
- switchAccount(accountId);
+ switchAccount(accountId, true); // Always go to inbox
}
@Override
@@ -434,7 +447,8 @@ class UIControllerOnePane extends UIControllerBase {
*/
private void commitFragmentTransaction(FragmentTransaction ft) {
if (!ft.isEmpty()) {
- ft.commit();
+ // STOPSHIP Don't use AllowingStateLoss. See b/4519430
+ ft.commitAllowingStateLoss();
mFragmentManager.executePendingTransactions();
}
}
diff --git a/src/com/android/email/activity/UIControllerTwoPane.java b/src/com/android/email/activity/UIControllerTwoPane.java
index f75c7eb37..571763d46 100644
--- a/src/com/android/email/activity/UIControllerTwoPane.java
+++ b/src/com/android/email/activity/UIControllerTwoPane.java
@@ -44,10 +44,7 @@ import java.util.Set;
* so that we can easily switch between synchronous and asynchronous transactions.
*/
class UIControllerTwoPane extends UIControllerBase implements
- ThreePaneLayout.Callback,
- MailboxListFragment.Callback,
- MessageListFragment.Callback,
- MessageViewFragment.Callback {
+ ThreePaneLayout.Callback {
@VisibleForTesting
static final int MAILBOX_REFRESH_MIN_INTERVAL = 30 * 1000; // in milliseconds
@@ -75,8 +72,6 @@ class UIControllerTwoPane extends UIControllerBase implements
// ThreePaneLayoutCallback
@Override
public void onVisiblePanesChanged(int previousVisiblePanes) {
- refreshActionBar();
-
// If the right pane is gone, remove the message view.
final int visiblePanes = mThreePane.getVisiblePanes();
@@ -89,6 +84,7 @@ class UIControllerTwoPane extends UIControllerBase implements
if (isMessageListInstalled()) {
getMessageListFragment().onHidden((visiblePanes & ThreePaneLayout.PANE_MIDDLE) == 0);
}
+ refreshActionBar();
}
// MailboxListFragment$Callback
@@ -103,7 +99,9 @@ class UIControllerTwoPane extends UIControllerBase implements
// MailboxListFragment$Callback
@Override
public void onAccountSelected(long accountId) {
- switchAccount(accountId);
+ // It's from combined view, so "forceShowInbox" doesn't really matter.
+ // (We're always switching accounts.)
+ switchAccount(accountId, true);
}
// MailboxListFragment$Callback
@@ -427,7 +425,8 @@ class UIControllerTwoPane extends UIControllerBase implements
Log.d(Logging.LOG_TAG, this + " commitFragmentTransaction: " + ft);
}
if (!ft.isEmpty()) {
- ft.commit();
+ // STOPSHIP Don't use AllowingStateLoss. See b/4519430
+ ft.commitAllowingStateLoss();
mFragmentManager.executePendingTransactions();
}
}
@@ -818,12 +817,12 @@ class UIControllerTwoPane extends UIControllerBase implements
@Override
public void onAccountSelected(long accountId) {
- switchAccount(accountId);
+ switchAccount(accountId, false);
}
@Override
- public void onMailboxSelected(long mailboxId) {
- openMailbox(getUIAccountId(), mailboxId);
+ public void onMailboxSelected(long accountId, long mailboxId) {
+ openMailbox(accountId, mailboxId);
}
@Override
@@ -833,9 +832,32 @@ class UIControllerTwoPane extends UIControllerBase implements
}
@Override
- public boolean shouldShowMailboxName() {
- // Show when the left pane is hidden.
- return (mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_LEFT) == 0;
+ public int getTitleMode() {
+ final int visiblePanes = mThreePane.getVisiblePanes();
+ if ((mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_LEFT) != 0) {
+ // Mailbox list visible
+ return TITLE_MODE_ACCOUNT_NAME_ONLY;
+ }
+ if ((mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_MIDDLE) != 0) {
+ // Message list + message view
+ return TITLE_MODE_ACCOUNT_WITH_MAILBOX;
+ }
+ if ((mThreePane.getVisiblePanes() & ThreePaneLayout.PANE_RIGHT) != 0) {
+ // Message view only (message list collapsed)
+ // TODO return TITLE_MODE_MESSAGE_SUBJECT
+ return TITLE_MODE_ACCOUNT_WITH_MAILBOX;
+ }
+
+ // Shouldn't happen, but just in case
+ return TITLE_MODE_ACCOUNT_NAME_ONLY;
+ }
+
+ public String getMessageSubject() {
+ if (isMessageViewInstalled()) {
+ return "TODO: Return current message subject here";
+ } else {
+ return null;
+ }
}
@Override
@@ -843,7 +865,7 @@ class UIControllerTwoPane extends UIControllerBase implements
final int visiblePanes = mThreePane.getVisiblePanes();
final boolean leftPaneHidden = ((visiblePanes & ThreePaneLayout.PANE_LEFT) == 0);
return leftPaneHidden
- || (isMailboxListInstalled() && !getMailboxListFragment().isRoot());
+ || (isMailboxListInstalled() && getMailboxListFragment().canNavigateUp());
}
@Override
diff --git a/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java b/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java
index 97b0a6712..16e258ad7 100644
--- a/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java
+++ b/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java
@@ -52,7 +52,7 @@ public class AccountSelectorAdapterAccountsLoaderTest extends LoaderTestCase {
{
// Only 1 account -- no combined view row.
Loader l = new AccountSelectorAdapter.AccountsLoader(mProviderContext, 0L,
- true);
+ 0L, true);
AccountSelectorAdapter.CursorWithExtras result =
(AccountSelectorAdapter.CursorWithExtras) getLoaderResultSynchronously(l);
assertEquals(1, result.getAccountCount());
@@ -64,7 +64,7 @@ public class AccountSelectorAdapterAccountsLoaderTest extends LoaderTestCase {
{
// 2 accounts -- with combined view row, so returns 3 account rows.
Loader l = new AccountSelectorAdapter.AccountsLoader(mProviderContext, 0L,
- true);
+ 0L, true);
AccountSelectorAdapter.CursorWithExtras result =
(AccountSelectorAdapter.CursorWithExtras) getLoaderResultSynchronously(l);
assertEquals(3, result.getAccountCount());