Merge "Don't navigate to a shortcut mailbox"

This commit is contained in:
Todd Kennedy 2011-05-26 14:56:50 -07:00 committed by Android (Google) Code Review
commit b59b9d04d5
5 changed files with 172 additions and 20 deletions

View File

@ -20,6 +20,7 @@ import com.android.email.Email;
import com.android.email.FolderProperties;
import com.android.email.R;
import com.android.email.data.ClosingMatrixCursor;
import com.android.email.data.CursorWithExtras;
import com.android.email.data.ThrottlingCursorLoader;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent;
@ -36,6 +37,7 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.database.MergeCursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@ -217,7 +219,7 @@ import android.widget.TextView;
}
/**
* Loader for mailboxes of an account.
* Loads mailboxes that are the children of a given mailbox ID.
*/
private static class MailboxFragmentLoader extends ThrottlingCursorLoader {
private final Context mContext;
@ -247,6 +249,17 @@ import android.widget.TextView;
@Override
public Cursor loadInBackground() {
final Cursor childMailboxCursor = super.loadInBackground();
final Cursor returnCursor;
final Bundle extras = new Bundle();
// Setup the extras to return along with the cursor
int cursorCount = childMailboxCursor.getCount();
extras.putInt(CursorWithExtras.EXTRA_MAILBOX_CHILD_COUNT, cursorCount);
long nextParentKey = findParentWithChildren(mParentKey);
extras.putLong(CursorWithExtras.EXTRA_MAILBOX_NEXT_PARENT_ID, nextParentKey);
Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mParentKey);
long grandParentKey = mailbox == null ? Mailbox.NO_MAILBOX : mailbox.mParentKey;
extras.putLong(CursorWithExtras.EXTRA_MAILBOX_PARENT_ID, grandParentKey);
// If we're not showing the top level mailboxes, add the "parent" mailbox.
if (mParentKey != Mailbox.NO_MAILBOX) {
@ -254,24 +267,47 @@ import android.widget.TextView;
Mailbox.CONTENT_URI, CURMAILBOX_PROJECTION, MAILBOX_SELECTION,
new String[] { Long.toString(mAccountId), Long.toString(mParentKey) },
null);
return Utility.CloseTraceCursorWrapper.get(new MergeCursor(
new Cursor[] { parentCursor, childMailboxCursor }));
returnCursor = new MergeCursor(new Cursor[] { parentCursor, childMailboxCursor });
} else {
// Add "Starred", only if the account has at least one starred message.
// TODO It's currently "combined starred", but the plan is to make it per-account
// starred.
final int accountStarredCount
= Message.getFavoriteMessageCount(mContext, mAccountId);
if (accountStarredCount > 0) {
final MatrixCursor starredCursor = new MatrixCursor(getProjection());
final int totalStarredCount = Message.getFavoriteMessageCount(mContext);
addCombinedMailboxRow(starredCursor, Mailbox.QUERY_ALL_FAVORITES,
Mailbox.TYPE_MAIL, totalStarredCount, true);
returnCursor
= new MergeCursor(new Cursor[] { starredCursor, childMailboxCursor });
} else {
returnCursor = childMailboxCursor; // no starred message
}
}
// Add "Starred", only if the account has at least one starred message.
// TODO It's currently "combined starred", but the plan is to make it per-account
// starred.
final int accountStarredCount = Message.getFavoriteMessageCount(mContext, mAccountId);
if (accountStarredCount > 0) {
final MatrixCursor starredCursor = new MatrixCursor(getProjection());
final int totalStarredCount = Message.getFavoriteMessageCount(mContext);
addCombinedMailboxRow(starredCursor, Mailbox.QUERY_ALL_FAVORITES, Mailbox.TYPE_MAIL,
totalStarredCount, true);
return Utility.CloseTraceCursorWrapper.get(
new MergeCursor(new Cursor[] { starredCursor, childMailboxCursor }));
}
return new CursorWithExtras(Utility.CloseTraceCursorWrapper.get(returnCursor), extras);
}
return Utility.CloseTraceCursorWrapper.get(childMailboxCursor); // no starred message
/**
* Returns the next parent mailbox with at least one child mailbox. If the given
* mailbox does not exist in the database, returns {@link Mailbox#NO_MAILBOX}. If
* we reach the root parent and we still don't have children, returns
* {@link Mailbox#NO_MAILBOX}.
*/
private long findParentWithChildren(long mailboxId) {
int childCount = Mailbox.count(mContext, Mailbox.CONTENT_URI,
MAILBOX_SELECTION_WITH_PARENT,
new String[] { Long.toString(mAccountId), Long.toString(mailboxId) });
if (childCount == 0 && mailboxId != Mailbox.NO_MAILBOX) {
// There are no children; select parent
Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mailboxId);
if (mailbox == null) {
return Mailbox.NO_MAILBOX;
}
return findParentWithChildren(mailbox.mParentKey);
}
return mailboxId;
}
}
@ -297,7 +333,7 @@ import android.widget.TextView;
final Cursor accounts = super.loadInBackground();
// Build combined mailbox rows.
final MatrixCursor combinedWithAccounts = buildCombinedMailboxes(mContext, accounts);
final MatrixCursor returnCursor = buildCombinedMailboxes(mContext, accounts);
// Add account rows.
accounts.moveToPosition(-1);
@ -306,11 +342,11 @@ import android.widget.TextView;
final String accountName = accounts.getString(COLUMN_ACCOUNT_DISPLAY_NAME);
final int unreadCount = Mailbox.getUnreadCountByAccountAndMailboxType(
mContext, accountId, Mailbox.TYPE_INBOX);
addMailboxRow(combinedWithAccounts, accountId, accountName, Mailbox.TYPE_NONE,
addMailboxRow(returnCursor, accountId, accountName, Mailbox.TYPE_NONE,
unreadCount, unreadCount, ROW_TYPE_ACCOUNT, Mailbox.FLAG_NONE,
accountId);
}
return Utility.CloseTraceCursorWrapper.get(combinedWithAccounts);
return Utility.CloseTraceCursorWrapper.get(returnCursor);
}
/*package*/ static MatrixCursor buildCombinedMailboxes(Context context,

View File

@ -20,6 +20,7 @@ import com.android.email.Controller;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.RefreshManager;
import com.android.email.data.CursorWithExtras;
import com.android.email.provider.EmailProvider;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Account;
@ -120,7 +121,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
private int mDragItemHeight = -1;
/** Task that actually does the work to auto-expand folder lists during drag-n-drop */
private TimerTask mDragTimerTask;
// True if we are currently scrolling under the drag item
/** {@code true} if we are currently scrolling under the drag item */
private boolean mTargetScrolling;
private Parcelable mSavedListState;
@ -150,6 +151,15 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
*/
public void onMailboxSelected(long accountId, long mailboxId, boolean navigate);
/**
* Called if the mailbox ID is being requested to change. This could occur for several
* reasons; such as if the current, navigated mailbox has no more children.
* @param newMailboxId The new mailbox ID to use for displaying in the mailbox list
* @param selectedMailboxId The new mailbox ID to highlight. If {@link Mailbox#NO_MAILBOX},
* the receiver may select any mailbox it chooses.
*/
public void requestMailboxChange(long newMailboxId, long selectedMailboxId);
/**
* Called when a mailbox is selected during D&D.
*/
@ -180,6 +190,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
@Override public void onAccountSelected(long accountId) { }
@Override public void onCurrentMailboxUpdated(long mailboxId, String mailboxName,
int unreadCount) { }
@Override public void requestMailboxChange(long newMailboxId, long selectedMailboxId) { }
}
/**
@ -461,6 +472,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
// TODO This class probably should be made static. There are many calls into the enclosing
// class and we need to be cautious about what we call while in these callbacks
private class MailboxListLoaderCallbacks implements LoaderCallbacks<Cursor> {
/** Whether or not the loader has finished at least once */
private boolean mIsFirstLoad;
@Override
@ -482,6 +494,28 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
// Note at this point we can assume the view is created.
// The loader manager doesn't deliver results when a fragment is stopped.
// Validate the cursor and make sure we're showing the "right thing"
if (cursor instanceof CursorWithExtras) {
CursorWithExtras c = (CursorWithExtras) cursor;
int childCount = c.getInt(CursorWithExtras.EXTRA_MAILBOX_CHILD_COUNT, -1);
if (childCount == 0) {
long nextParentId = c.getLong(CursorWithExtras.EXTRA_MAILBOX_NEXT_PARENT_ID);
long grandParentId = c.getLong(CursorWithExtras.EXTRA_MAILBOX_PARENT_ID);
long highlightId;
// Only set a mailbox highlight if we're choosing our immediate parent
if (grandParentId == nextParentId) {
highlightId = getParentMailboxId();
} else {
highlightId = Mailbox.NO_MAILBOX;
}
// If the next parent w/ children isn't us, request a change
if (nextParentId != getParentMailboxId()) {
mCallback.requestMailboxChange(nextParentId, highlightId);
return;
}
}
}
if (cursor.getCount() == 0) {
// If there's no row, don't set it to the ListView.
// Instead use setListShown(false) to make ListFragment show progress icon.

View File

@ -82,6 +82,10 @@ class UIControllerOnePane extends UIControllerBase {
public void onMailboxSelectedForDnD(long mailboxId) {
// No drag&drop on 1-pane
}
@Override
public void requestMailboxChange(long newMailboxId, long selectedMailboxId) {
}
};
private final MessageListFragment.Callback mMessageListFragmentCallback =

View File

@ -184,6 +184,7 @@ class UIControllerTwoPane extends UIControllerBase implements
}
}
@Override
public void onMailboxSelectedForDnD(long mailboxId) {
// STOPSHIP the new mailbox list created here doesn't know D&D is in progress. b/4332725
@ -191,6 +192,25 @@ class UIControllerTwoPane extends UIControllerBase implements
false /* don't clear message list and message view */);
}
@Override
public void requestMailboxChange(final long newMailboxId, final long selectedMailboxId) {
// Unfortunately if the screen rotates while the task is running, we just cancel the task
// so mailbox change request will be gone. But we'll live with it as it's not too critical.
new EmailAsyncTask<Void, Void, Void>(mTaskTracker) {
@Override protected Void doInBackground(Void... params) { return null; }
@Override protected void onPostExecute(Void mailboxId) {
if (selectedMailboxId == getMailboxListMailboxId()) {
// We're not changing selections; just the contents of the mailbox list
updateMailboxList(getActualAccountId(), newMailboxId, false);
mMailboxListFragment.setSelectedMailbox(selectedMailboxId);
} else {
// Select a whole new mailbox
openMailbox(getActualAccountId(), newMailboxId);
}
}
}.cancelPreviousAndExecuteSerial();
}
// MailboxListFragment$Callback
@Override
public void onAccountSelected(long accountId) {

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.data;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.os.Bundle;
/**
* A special cursor that contains additional data.
*
* <p>TODO Use this instead of EmailWidgetLoader$CursorWithCounts.
*/
public class CursorWithExtras extends CursorWrapper {
/** The number of children in a mailbox. If set, must be a positive value. */
public final static String EXTRA_MAILBOX_CHILD_COUNT = "mailboxChildCount";
/** The ID of the next, immediate parent mailbox */
public final static String EXTRA_MAILBOX_PARENT_ID = "mailboxParentId";
/** The ID of the next mailbox in the hierarchy with at least one child */
public final static String EXTRA_MAILBOX_NEXT_PARENT_ID = "mailboxNextParentId";
private final Bundle mExtras;
public CursorWithExtras(Cursor cursor, Bundle extras) {
super(cursor);
mExtras = extras;
}
public int getInt(String key) {
return getInt(key, 0);
}
public int getInt(String key, int defaultValue) {
return mExtras == null ? defaultValue : mExtras.getInt(key);
}
public long getLong(String key) {
return getLong(key, 0L);
}
public long getLong(String key, long defaultValue) {
return mExtras == null ? defaultValue : mExtras.getLong(key);
}
}