diff --git a/res/values/strings.xml b/res/values/strings.xml
index 55db0c6bc..cddfc7c36 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -276,6 +276,9 @@
Show all folders
Accounts
+
+
+ Recent mailboxes(%s)
Load more messages
diff --git a/src/com/android/email/activity/AccountSelectorAdapter.java b/src/com/android/email/activity/AccountSelectorAdapter.java
index 2f800c7c2..996e3b236 100644
--- a/src/com/android/email/activity/AccountSelectorAdapter.java
+++ b/src/com/android/email/activity/AccountSelectorAdapter.java
@@ -23,9 +23,13 @@ import com.android.email.data.ClosingMatrixCursor;
import com.android.email.data.ThrottlingCursorLoader;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
+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.ContentUris;
import android.content.Context;
import android.content.Loader;
import android.database.Cursor;
@@ -47,11 +51,14 @@ public class AccountSelectorAdapter extends CursorAdapter {
private static final String UNREAD_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";
private static final int ROW_TYPE_HEADER = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
@SuppressWarnings("unused")
private static final int ROW_TYPE_MAILBOX = 0;
private static final int ROW_TYPE_ACCOUNT = 1;
private static final int ITEM_VIEW_TYPE_ACCOUNT = 0;
+ private static final int UNKNOWN_POSITION = -1;
/** Projection for account database query */
private static final String[] ACCOUNT_PROJECTION = new String[] {
Account.ID,
@@ -68,6 +75,7 @@ public class AccountSelectorAdapter extends CursorAdapter {
Account.DISPLAY_NAME,
Account.EMAIL_ADDRESS,
UNREAD_COUNT,
+ ACCOUNT_POSITION,
};
/** Sort order. Show the default account first. */
@@ -78,8 +86,13 @@ public class AccountSelectorAdapter extends CursorAdapter {
@SuppressWarnings("hiding")
private final Context mContext;
- public static Loader createLoader(Context context) {
- return new AccountsLoader(context);
+ /**
+ * Returns a loader that can populate the account spinner.
+ * @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);
}
public AccountSelectorAdapter(Context context) {
@@ -88,6 +101,22 @@ public class AccountSelectorAdapter extends CursorAdapter {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
+ /**
+ * 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);
+ }
+
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
Cursor c = getCursor();
@@ -175,6 +204,11 @@ public class AccountSelectorAdapter extends CursorAdapter {
return c.moveToPosition(position) ? getAccountUnreadCount(c) : 0;
}
+ private int getAccountPosition(int position) {
+ final Cursor c = getCursor();
+ return c.moveToPosition(position) ? getAccountPosition(c) : UNKNOWN_POSITION;
+ }
+
/** Returns the account ID extracted from the given cursor. */
static long getAccountId(Cursor c) {
return c.getLong(c.getColumnIndex(Account.ID));
@@ -195,6 +229,11 @@ public class AccountSelectorAdapter extends CursorAdapter {
return cursor.getInt(cursor.getColumnIndex(UNREAD_COUNT));
}
+ /** Returns the account position extracted from the given cursor. */
+ private static int getAccountPosition(Cursor cursor) {
+ return cursor.getInt(cursor.getColumnIndex(ACCOUNT_POSITION));
+ }
+
/**
* Load the account list. The resulting cursor contains
* - Account info
@@ -204,12 +243,13 @@ public class AccountSelectorAdapter extends CursorAdapter {
@VisibleForTesting
static class AccountsLoader extends ThrottlingCursorLoader {
private final Context mContext;
-
- public AccountsLoader(Context context) {
+ private final long mAccountId;
+ public AccountsLoader(Context context, long accountId) {
// Super class loads a regular account cursor, but we replace it in loadInBackground().
super(context, EmailContent.Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null,
ORDER_BY);
mContext = context;
+ mAccountId = accountId;
}
@Override
@@ -218,47 +258,100 @@ public class AccountSelectorAdapter extends CursorAdapter {
// Use ClosingMatrixCursor so that accountsCursor gets closed too when it's closed.
final MatrixCursor resultCursor
= new ClosingMatrixCursor(ADAPTER_PROJECTION, accountsCursor);
- addAccountsToCursor(resultCursor, accountsCursor);
- // TODO Add mailbox recent list to the end of the return cursor
+ final int accountPosition = addAccountsToCursor(resultCursor, accountsCursor);
+ addRecentsToCursor(resultCursor, accountPosition);
return Utility.CloseTraceCursorWrapper.get(resultCursor);
}
/** Adds the account list [with extra meta data] to the given matrix cursor */
- private void addAccountsToCursor(MatrixCursor matrixCursor, Cursor accountCursor) {
+ private int addAccountsToCursor(MatrixCursor matrixCursor, Cursor accountCursor) {
+ int accountPosition = UNKNOWN_POSITION;
accountCursor.moveToPosition(-1);
// Add a header for the accounts
- matrixCursor.newRow()
- .add(ROW_TYPE_HEADER)
- .add(0L)
- .add(mContext.getString(R.string.mailbox_list_account_selector_account_header))
- .add(null)
- .add(0L);
+ String header =
+ mContext.getString(R.string.mailbox_list_account_selector_account_header);
+ addRow(matrixCursor, ROW_TYPE_HEADER, 0L, header, null, 0, UNKNOWN_POSITION);
int totalUnread = 0;
+ int currentPosition = 1;
while (accountCursor.moveToNext()) {
// Add account, with its unread count.
final long accountId = accountCursor.getLong(0);
final int unread = Mailbox.getUnreadCountByAccountAndMailboxType(
mContext, accountId, Mailbox.TYPE_INBOX);
- matrixCursor.newRow()
- .add(ROW_TYPE_ACCOUNT)
- .add(accountId)
- .add(getAccountDisplayName(accountCursor))
- .add(getAccountEmailAddress(accountCursor))
- .add(unread);
+ final String name = getAccountDisplayName(accountCursor);
+ final String emailAddress = getAccountEmailAddress(accountCursor);
+ addRow(matrixCursor, ROW_TYPE_ACCOUNT, accountId, name, emailAddress, unread,
+ UNKNOWN_POSITION);
totalUnread += unread;
+ if (accountId == mAccountId) {
+ accountPosition = currentPosition;
+ }
+ currentPosition++;
}
// Add "combined view" if more than one account exists
final int countAccounts = matrixCursor.getCount();
if (countAccounts > 1) {
- matrixCursor.newRow()
- .add(ROW_TYPE_ACCOUNT)
- .add(Account.ACCOUNT_ID_COMBINED_VIEW)
- .add(mContext.getResources().getString(
- R.string.mailbox_list_account_selector_combined_view))
- .add(mContext.getResources().getQuantityString(R.plurals.number_of_accounts,
- countAccounts, countAccounts))
- .add(totalUnread);
+ 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);
}
+ return accountPosition;
+ }
+
+ /**
+ * Adds the recent mailbox list to the given cursor.
+ * @param matrixCursor the cursor to add the list to
+ * @param accountPosition the cursor position of the currently selected account
+ */
+ private void addRecentsToCursor(MatrixCursor matrixCursor, int accountPosition) {
+ if (mAccountId <= 0L || mAccountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
+ // Currently selected account isn't usable for our purposes
+ return;
+ }
+ String emailAddress = null;
+ if (accountPosition != UNKNOWN_POSITION) {
+ matrixCursor.moveToPosition(accountPosition);
+ emailAddress =
+ matrixCursor.getString(matrixCursor.getColumnIndex(Account.EMAIL_ADDRESS));
+ }
+ boolean useTwoPane = mContext.getResources().getBoolean(R.bool.use_two_pane);
+ // Filter system mailboxes if we're using a two-pane view
+ RecentMailboxManager mailboxManager = RecentMailboxManager.getInstance(mContext);
+ ArrayList recentMailboxes = mailboxManager.getMostRecent(mAccountId, useTwoPane);
+ if (!useTwoPane && recentMailboxes.size() == 0) {
+ // TODO Add default mailboxes to recentMailboxes for the one pane view
+ }
+ if (recentMailboxes.size() > 0) {
+ 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);
+ for (long mailboxId : recentMailboxes) {
+ final int unread = Utility.getFirstRowInt(mContext,
+ ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
+ new String[] { MailboxColumns.UNREAD_COUNT }, null, null, null, 0);
+ final Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mailboxId);
+ addRow(matrixCursor, ROW_TYPE_MAILBOX, mailboxId, mailbox.mDisplayName, null,
+ unread, accountPosition);
+ }
+ }
+ if (!useTwoPane) {
+ // TODO Add row to view all mailboxes
+ }
+ }
+
+ /** Adds a row to the given cursor */
+ private void addRow(MatrixCursor cursor, int rowType, long id, String name,
+ String emailAddress, int unreadCount, int listPosition) {
+ cursor.newRow()
+ .add(rowType)
+ .add(id)
+ .add(name)
+ .add(emailAddress)
+ .add(unreadCount)
+ .add(listPosition);
}
}
}
diff --git a/src/com/android/email/activity/ActionBarController.java b/src/com/android/email/activity/ActionBarController.java
index c20e19275..3891a537f 100644
--- a/src/com/android/email/activity/ActionBarController.java
+++ b/src/com/android/email/activity/ActionBarController.java
@@ -18,6 +18,7 @@ package com.android.email.activity;
import com.android.email.R;
import com.android.emailcommon.provider.EmailContent.Account;
+import com.android.emailcommon.provider.Mailbox;
import android.app.ActionBar;
import android.app.LoaderManager;
@@ -51,7 +52,7 @@ public class ActionBarController {
private final AccountSelectorAdapter mAccountsSelectorAdapter;
private Cursor mAccountCursor;
/** The current account ID; used to determine if the account has changed. */
- private long mLastAccountIdForDirtyCheck = -1;
+ private long mLastAccountIdForDirtyCheck = Account.NO_ACCOUNT;
public final Callback mCallback;
@@ -81,12 +82,17 @@ public class ActionBarController {
/**
* Called when an account is selected on the account spinner.
- *
- * @param accountId ID of the selected account, or
- * {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
+ * @param accountId ID of the selected account, or {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
*/
public void onAccountSelected(long accountId);
+ /**
+ * Invoked when a recent mailbox is selected on the account spinner.
+ * @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);
+
/** Called when no accounts are found in the database. */
public void onNoAccountsFound();
}
@@ -142,8 +148,13 @@ public class ActionBarController {
// Update the account list only when the account has changed.
if (mLastAccountIdForDirtyCheck != mCallback.getUIAccountId()) {
mLastAccountIdForDirtyCheck = mCallback.getUIAccountId();
- // TODO Need to do this all the time as the recent list is shown here
- updateAccountList();
+ // 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();
+ }
}
}
@@ -155,7 +166,7 @@ public class ActionBarController {
new LoaderCallbacks() {
@Override
public Loader onCreateLoader(int id, Bundle args) {
- return AccountSelectorAdapter.createLoader(mContext);
+ return AccountSelectorAdapter.createLoader(mContext, mCallback.getUIAccountId());
}
@Override
@@ -235,8 +246,8 @@ public class ActionBarController {
if (mAccountsSelectorAdapter.isAccountItem(itemPosition)
&& itemId != mCallback.getUIAccountId()) {
mCallback.onAccountSelected(itemId);
- } else {
- // TODO handle mailbox item
+ } else if (!mAccountsSelectorAdapter.isAccountItem(itemPosition)) {
+ mCallback.onMailboxSelected(itemId);
}
return true;
}
diff --git a/src/com/android/email/activity/MessageViewFragmentBase.java b/src/com/android/email/activity/MessageViewFragmentBase.java
index 582e2df75..e94d5e5af 100644
--- a/src/com/android/email/activity/MessageViewFragmentBase.java
+++ b/src/com/android/email/activity/MessageViewFragmentBase.java
@@ -1026,6 +1026,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
reloadUiFromMessage(message, mOkToFetch);
queryContactStatus();
onMessageShown(mMessageId, mMailboxType);
+ RecentMailboxManager.getInstance(mContext).touch(message.mMailboxKey);
}
}
diff --git a/src/com/android/email/activity/UIControllerOnePane.java b/src/com/android/email/activity/UIControllerOnePane.java
index 1e9c38883..6cb4fd58e 100644
--- a/src/com/android/email/activity/UIControllerOnePane.java
+++ b/src/com/android/email/activity/UIControllerOnePane.java
@@ -237,6 +237,11 @@ class UIControllerOnePane extends UIControllerBase {
return UIControllerOnePane.this.getUIAccountId();
}
+ @Override
+ public void onMailboxSelected(long mailboxId) {
+ // TODO Implement this
+ }
+
@Override
public boolean isAccountSelected() {
return UIControllerOnePane.this.isAccountSelected();
diff --git a/src/com/android/email/activity/UIControllerTwoPane.java b/src/com/android/email/activity/UIControllerTwoPane.java
index 58d09b09e..22f945119 100644
--- a/src/com/android/email/activity/UIControllerTwoPane.java
+++ b/src/com/android/email/activity/UIControllerTwoPane.java
@@ -31,7 +31,6 @@ import com.android.emailcommon.utility.EmailAsyncTask;
import com.google.common.annotations.VisibleForTesting;
import android.app.Activity;
-import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
@@ -954,6 +953,11 @@ class UIControllerTwoPane extends UIControllerBase implements
switchAccount(accountId);
}
+ @Override
+ public void onMailboxSelected(long mailboxId) {
+ UIControllerTwoPane.this.openMailbox(getUIAccountId(), mailboxId);
+ }
+
@Override
public void onNoAccountsFound() {
Welcome.actionStart(mActivity);
diff --git a/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java b/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java
index b98401428..43f57a0c3 100644
--- a/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java
+++ b/tests/src/com/android/email/activity/AccountSelectorAdapterAccountsLoaderTest.java
@@ -46,7 +46,7 @@ public class AccountSelectorAdapterAccountsLoaderTest extends LoaderTestCase {
final Account a1 = ProviderTestUtils.setupAccount("a1", true, mProviderContext);
{
// Only 1 account -- no combined view row.
- Loader l = new AccountSelectorAdapter.AccountsLoader(mProviderContext);
+ Loader l = new AccountSelectorAdapter.AccountsLoader(mProviderContext, 0L);
Cursor result = getLoaderResultSynchronously(l);
assertEquals(1, result.getCount());
}
@@ -54,7 +54,7 @@ public class AccountSelectorAdapterAccountsLoaderTest extends LoaderTestCase {
final Account a2 = ProviderTestUtils.setupAccount("a2", true, mProviderContext);
{
// 2 accounts -- with combined view row, so returns 3 rows.
- Loader l = new AccountSelectorAdapter.AccountsLoader(mProviderContext);
+ Loader l = new AccountSelectorAdapter.AccountsLoader(mProviderContext, 0L);
Cursor result = getLoaderResultSynchronously(l);
assertEquals(3, result.getCount());
}