diff --git a/emailcommon/src/com/android/emailcommon/utility/Utility.java b/emailcommon/src/com/android/emailcommon/utility/Utility.java index 5bfae1ed2..96dce4834 100644 --- a/emailcommon/src/com/android/emailcommon/utility/Utility.java +++ b/emailcommon/src/com/android/emailcommon/utility/Utility.java @@ -75,6 +75,8 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Set; import java.util.TimeZone; import java.util.regex.Pattern; @@ -902,6 +904,8 @@ public class Utility { } public static long[] toPrimitiveLongArray(Collection collection) { + // Need to do this manually because we're converting to a primitive long array, not + // a Long array. final int size = collection.size(); final long[] ret = new long[size]; // Collection doesn't have get(i). (Iterable doesn't have size()) @@ -912,6 +916,17 @@ public class Utility { return ret; } + public static Set toLongSet(long[] array) { + // Need to do this manually because we're converting from a primitive long array, not + // a Long array. + final int size = array.length; + HashSet ret = new HashSet(size); + for (int i = 0; i < size; i++) { + ret.add(array[i]); + } + return ret; + } + /** * Workaround for the {@link ListView#smoothScrollToPosition} randomly scroll the view bug * if it's called right after {@link ListView#setAdapter}. diff --git a/src/com/android/email/activity/MessageListFragment.java b/src/com/android/email/activity/MessageListFragment.java index f556a9e85..37c1f70ba 100644 --- a/src/com/android/email/activity/MessageListFragment.java +++ b/src/com/android/email/activity/MessageListFragment.java @@ -736,7 +736,7 @@ public class MessageListFragment extends ListFragment } } - private void moveMessages(Set selectedSet) { + private void showMoveMessagesDialog(Set selectedSet) { long[] messageIds = Utility.toPrimitiveLongArray(selectedSet); MoveMessageToDialog dialog = MoveMessageToDialog.newInstance(messageIds, this); dialog.show(getFragmentManager(), "dialog"); @@ -744,6 +744,7 @@ public class MessageListFragment extends ListFragment @Override public void onMoveToMailboxSelected(long newMailboxId, long[] messageIds) { + mCallback.onAdvancingOpAccepted(Utility.toLongSet(messageIds)); ActivityHelper.moveMessages(getActivity(), newMailboxId, messageIds); // Move is async, so we can't refresh now. Instead, just clear the selection. @@ -1378,8 +1379,7 @@ public class MessageListFragment extends ListFragment deleteMessages(selectedConversations); break; case R.id.move: - mCallback.onAdvancingOpAccepted(selectedConversations); - moveMessages(selectedConversations); + showMoveMessagesDialog(selectedConversations); break; } return true; diff --git a/src/com/android/email/activity/MessageListXLFragmentManager.java b/src/com/android/email/activity/MessageListXLFragmentManager.java index 74db6aaaa..c7722eeca 100644 --- a/src/com/android/email/activity/MessageListXLFragmentManager.java +++ b/src/com/android/email/activity/MessageListXLFragmentManager.java @@ -49,7 +49,6 @@ import java.util.Set; * TODO Refine "move to". */ class MessageListXLFragmentManager implements - MoveMessageToDialog.Callback, MailboxFinder.Callback, ThreePaneLayout.Callback, MailboxListFragment.Callback, @@ -178,13 +177,6 @@ class MessageListXLFragmentManager implements Log.e(Logging.LOG_TAG, "unable to find mailbox"); } - // MoveMessageToDialog$Callback - @Override - public void onMoveToMailboxSelected(long newMailboxId, long[] messageIds) { - ActivityHelper.moveMessages(mActivity, newMailboxId, messageIds); - onCurrentMessageGone(); - } - // ThreePaneLayoutCallback @Override public void onVisiblePanesChanged(int previousVisiblePanes) { @@ -258,6 +250,11 @@ class MessageListXLFragmentManager implements */ @Override public void onAdvancingOpAccepted(Set affectedMessages) { + if (!isMessageSelected()) { + // Do nothing if message view is not visible. + return; + } + int autoAdvanceDir = Preferences.getPreferences(mActivity).getAutoAdvanceDirection(); if ((autoAdvanceDir == Preferences.AUTO_ADVANCE_MESSAGE_LIST) || (mOrderManager == null)) { if (affectedMessages.contains(getMessageId())) { @@ -346,17 +343,10 @@ class MessageListXLFragmentManager implements } @Override - public void onBeforeMessageDelete() { + public void onBeforeMessageGone() { 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()); diff --git a/src/com/android/email/activity/MessageView.java b/src/com/android/email/activity/MessageView.java index 577814376..8f3ba8ca1 100644 --- a/src/com/android/email/activity/MessageView.java +++ b/src/com/android/email/activity/MessageView.java @@ -368,12 +368,7 @@ public class MessageView extends MessageViewBase implements View.OnClickListener } @Override - public void onBeforeMessageDelete() { - // TODO Implement this - } - - @Override - public void onMoveMessage() { + public void onBeforeMessageGone() { // TODO Implement this } } diff --git a/src/com/android/email/activity/MessageViewFragment.java b/src/com/android/email/activity/MessageViewFragment.java index 6f8834772..f8fea13c8 100644 --- a/src/com/android/email/activity/MessageViewFragment.java +++ b/src/com/android/email/activity/MessageViewFragment.java @@ -50,7 +50,7 @@ import java.security.InvalidParameterException; * See {@link MessageViewBase} for the class relation diagram. */ public class MessageViewFragment extends MessageViewFragmentBase - implements CheckBox.OnCheckedChangeListener { + implements CheckBox.OnCheckedChangeListener, MoveMessageToDialog.Callback { /** Argument name(s) */ private static final String ARG_MESSAGE_ID = "messageId"; @@ -107,13 +107,12 @@ public class MessageViewFragment extends MessageViewFragmentBase public void onMessageSetUnread(); /** - * Called right before the current message will be deleted. - * Callees don't have to delete messages. The fragment does. + * Called right before the current message will be deleted or moved to another mailbox. + * + * Callees will usually close the fragment. */ - public void onBeforeMessageDelete(); + public void onBeforeMessageGone(); - /** Called when the move button is pressed. */ - public void onMoveMessage(); /** Called when the forward button is pressed. */ public void onForward(); /** Called when the reply button is pressed. */ @@ -130,8 +129,7 @@ public class MessageViewFragment extends MessageViewFragmentBase @Override public void onCalendarLinkClicked(long epochEventStartTime) { } @Override public void onMessageSetUnread() { } @Override public void onRespondedToInvite(int response) { } - @Override public void onBeforeMessageDelete() { } - @Override public void onMoveMessage() { } + @Override public void onBeforeMessageGone() { } @Override public void onForward() { } @Override public void onReply() { } @Override public void onReplyAll() { } @@ -415,11 +413,22 @@ public class MessageViewFragment extends MessageViewFragmentBase } private void onMove() { - mCallback.onMoveMessage(); + // STOPSHIP mCurrentMessageId is not a good one to use here. See b/4346486 + // (We use it for now just to keep it consistent with onDelete) + MoveMessageToDialog dialog = MoveMessageToDialog.newInstance(new long[] {mCurrentMessageId}, + this); + dialog.show(getFragmentManager(), "dialog"); + } + + // MoveMessageToDialog$Callback + @Override + public void onMoveToMailboxSelected(long newMailboxId, long[] messageIds) { + mCallback.onBeforeMessageGone(); + ActivityHelper.moveMessages(mContext, newMailboxId, messageIds); } private void onDelete() { - mCallback.onBeforeMessageDelete(); + mCallback.onBeforeMessageGone(); ActivityHelper.deleteMessage(mContext, mCurrentMessageId); } diff --git a/src/com/android/email/activity/MoveMessageToDialog.java b/src/com/android/email/activity/MoveMessageToDialog.java index 82199d2c2..7c25d00ad 100644 --- a/src/com/android/email/activity/MoveMessageToDialog.java +++ b/src/com/android/email/activity/MoveMessageToDialog.java @@ -16,7 +16,9 @@ package com.android.email.activity; +import com.android.email.Email; 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 com.android.emailcommon.provider.EmailContent.Message; @@ -35,6 +37,7 @@ import android.content.Loader; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; +import android.util.Log; import java.security.InvalidParameterException; @@ -68,25 +71,29 @@ public class MoveMessageToDialog extends DialogFragment implements DialogInterfa * * @param messageIds IDs of the messages to be moved. * @param callbackFragment Fragment that gets a callback. The fragment must implement - * {@link Callback}. If null is passed, then the owner activity is used instead, in which case - * it must implement {@link Callback} instead. + * {@link Callback}. */ - public static MoveMessageToDialog newInstance(long[] messageIds, Fragment callbackFragment) { + public static MoveMessageToDialog newInstance(long[] messageIds, + T callbackFragment) { if (messageIds.length == 0) { throw new InvalidParameterException(); } + if (callbackFragment == null) { + throw new IllegalArgumentException(); // fail fast + } MoveMessageToDialog dialog = new MoveMessageToDialog(); Bundle args = new Bundle(); args.putLongArray(BUNDLE_MESSAGE_IDS, messageIds); dialog.setArguments(args); - if (callbackFragment != null) { - dialog.setTargetFragment(callbackFragment, 0); - } + dialog.setTargetFragment(callbackFragment, 0); return dialog; } @Override public void onCreate(Bundle savedInstanceState) { + if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { + Log.d(Logging.LOG_TAG, "" + this + " onCreate target=" + getTargetFragment()); + } super.onCreate(savedInstanceState); mMessageIds = getArguments().getLongArray(BUNDLE_MESSAGE_IDS); setStyle(STYLE_NORMAL, android.R.style.Theme_Holo_Light); @@ -121,20 +128,10 @@ public class MoveMessageToDialog extends DialogFragment implements DialogInterfa public void onClick(DialogInterface dialog, int position) { final long mailboxId = mAdapter.getItemId(position); - getCallback().onMoveToMailboxSelected(mailboxId, mMessageIds); + ((Callback) getTargetFragment()).onMoveToMailboxSelected(mailboxId, mMessageIds); dismiss(); } - private Callback getCallback() { - Fragment targetFragment = getTargetFragment(); - if (targetFragment != null) { - // If a target is set, it MUST implement Callback. - return (Callback) targetFragment; - } - // If not the parent activity MUST implement Callback. - return (Callback) getActivity(); - } - /** * Delay-call {@link #dismissAllowingStateLoss()} using a {@link Handler}. Calling * {@link #dismissAllowingStateLoss()} from {@link LoaderManager.LoaderCallbacks#onLoadFinished} diff --git a/tests/src/com/android/emailcommon/utility/UtilityUnitTests.java b/tests/src/com/android/emailcommon/utility/UtilityUnitTests.java index 4d428bb75..3f629c46f 100644 --- a/tests/src/com/android/emailcommon/utility/UtilityUnitTests.java +++ b/tests/src/com/android/emailcommon/utility/UtilityUnitTests.java @@ -334,6 +334,19 @@ public class UtilityUnitTests extends AndroidTestCase { assertEquals(4, two[1]); } + public void testToLongSet() { + assertEquals(0, Utility.toLongSet(new long[] {}).size()); + + final Set one = Utility.toLongSet(new long[] {1}); + assertEquals(1, one.size()); + assertTrue(one.contains(1L)); + + final Set two = Utility.toLongSet(new long[] {1, 2}); + assertEquals(2, two.size()); + assertTrue(two.contains(1L)); + assertTrue(two.contains(2L)); + } + public void testGetContentFileName() throws Exception { Context providerContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext( mContext); @@ -359,6 +372,7 @@ public class UtilityUnitTests extends AndroidTestCase { assertEquals(lastPathSegment, Utility.getContentFileName(providerContext, notExistUri)); } + // used by testToPrimitiveLongArray private static Collection createLongCollection(long... values) { ArrayList ret = new ArrayList(); for (long value : values) {