am 6a3d5ce0: Change the undo message for a "Move to" action

* commit '6a3d5ce0b18f58fcfa1af0315dc8ddc7331c2c5f':
  Change the undo message for a "Move to" action
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 84042ce..0039aab 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -21,4 +21,5 @@
     <item type="id" name="reply_state" />
     <item type="id" name="manage_folders_item"/>
     <item type="id" name="contact_image" />
+    <item type="id" name="move_folder" />
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c44e9af..dee3df6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -456,6 +456,9 @@
         <item quantity="other">Changed folders.</item>
     </plurals>
 
+    <!-- Displayed after moving a conversation to a different folder. [CHAR LIMIT=100] -->
+    <string name="conversation_folder_moved">Moved to <xliff:g id="folderName">%1$s</xliff:g></string>
+
     <!-- Search Results: Text for header that is shown above search results [CHAR LIMIT=30] -->
     <string name="search_results_header">Results</string>
     <!-- Toast shown when the user taps the search hard key when viewing an account that does not support search [CHAR LIMIT=100] -->
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index f2f86fb..0f07ef0 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -2277,7 +2277,7 @@
                     @Override
                     public void run() {
                         onUndoAvailable(new ToastBarOperation(mTarget.size(), mAction,
-                                ToastBarOperation.UNDO, mIsSelectedSet));
+                                ToastBarOperation.UNDO, mIsSelectedSet, mFolder));
                     }
                 }, mShowUndoBarDelay);
             }
@@ -2304,7 +2304,8 @@
     // conversations to.
     @Override
     public final void assignFolder(Collection<FolderOperation> folderOps,
-            Collection<Conversation> target, boolean batch, boolean showUndo) {
+            Collection<Conversation> target, boolean batch, boolean showUndo,
+            final boolean isMoveTo) {
         // Actions are destructive only when the current folder can be assigned
         // to (which is the same as being able to un-assign a conversation from the folder) and
         // when the list of folders contains the current folder.
@@ -2321,12 +2322,40 @@
         // Update the UI elements depending no their visibility and availability
         // TODO(viki): Consolidate this into a single method requestDelete.
         if (isDestructive) {
+            /*
+             * If this is a MOVE operation, we want the action folder to be the destination folder.
+             * Otherwise, we want it to be the current folder.
+             *
+             * A set of folder operations is a move if there are exactly two operations: an add and
+             * a remove.
+             */
+            final Folder actionFolder;
+            if (folderOps.size() != 2) {
+                actionFolder = mFolder;
+            } else {
+                Folder addedFolder = null;
+                boolean hasRemove = false;
+                for (final FolderOperation folderOperation : folderOps) {
+                    if (folderOperation.mAdd) {
+                        addedFolder = folderOperation.mFolder;
+                    } else {
+                        hasRemove = true;
+                    }
+                }
+
+                if (hasRemove && addedFolder != null) {
+                    actionFolder = addedFolder;
+                } else {
+                    actionFolder = mFolder;
+                }
+            }
+
             folderChange = getDeferredFolderChange(target, folderOps, isDestructive,
-                    batch, showUndo);
+                    batch, showUndo, isMoveTo, actionFolder);
             delete(0, target, folderChange);
         } else {
             folderChange = getFolderChange(target, folderOps, isDestructive,
-                    batch, showUndo);
+                    batch, showUndo, false /* isMoveTo */, mFolder);
             requestUpdate(folderChange);
         }
     }
@@ -2602,8 +2631,9 @@
         }
         // Drag and drop is destructive: we remove conversations from the
         // current folder.
-        final DestructiveAction action = getFolderChange(conversations, dragDropOperations,
-                isDestructive, true, true);
+        final DestructiveAction action =
+                getFolderChange(conversations, dragDropOperations, isDestructive,
+                        true /* isBatch */, true /* showUndo */, true /* isMoveTo */, folder);
         if (isDestructive) {
             delete(0, conversations, action);
         } else {
@@ -2671,7 +2701,7 @@
         @Override
         public void performAction() {
             ToastBarOperation undoOp = new ToastBarOperation(mConversations.size(),
-                    R.id.change_folder, ToastBarOperation.UNDO, true);
+                    R.id.change_folder, ToastBarOperation.UNDO, true /* batch */, mInitialFolder);
             onUndoAvailable(undoOp);
             ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
             ContentValues values = new ContentValues();
@@ -3132,20 +3162,23 @@
         private boolean mIsSelectedSet;
         private boolean mShowUndo;
         private int mAction;
+        private final Folder mActionFolder;
 
         /**
          * Create a new folder destruction object to act on the given conversations.
          * @param target conversations to act upon.
+         * @param actionFolder the {@link Folder} being acted upon, used for displaying the undo bar
          */
         private FolderDestruction(final Collection<Conversation> target,
                 final Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
-                boolean showUndo, int action) {
+                boolean showUndo, int action, final Folder actionFolder) {
             mTarget = ImmutableList.copyOf(target);
             mFolderOps.addAll(folders);
             mIsDestructive = isDestructive;
             mIsSelectedSet = isBatch;
             mShowUndo = showUndo;
             mAction = action;
+            mActionFolder = actionFolder;
         }
 
         @Override
@@ -3155,7 +3188,7 @@
             }
             if (mIsDestructive && mShowUndo) {
                 ToastBarOperation undoOp = new ToastBarOperation(mTarget.size(), mAction,
-                        ToastBarOperation.UNDO, mIsSelectedSet);
+                        ToastBarOperation.UNDO, mIsSelectedSet, mActionFolder);
                 onUndoAvailable(undoOp);
             }
             // For each conversation, for each operation, add/ remove the
@@ -3207,18 +3240,18 @@
 
     public final DestructiveAction getFolderChange(Collection<Conversation> target,
             Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
-            boolean showUndo) {
+            boolean showUndo, final boolean isMoveTo, final Folder actionFolder) {
         final DestructiveAction da = getDeferredFolderChange(target, folders, isDestructive,
-                isBatch, showUndo);
+                isBatch, showUndo, isMoveTo, actionFolder);
         registerDestructiveAction(da);
         return da;
     }
 
     public final DestructiveAction getDeferredFolderChange(Collection<Conversation> target,
             Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
-            boolean showUndo) {
-        return new FolderDestruction(target, folders, isDestructive, isBatch,
-                showUndo, R.id.change_folder);
+            boolean showUndo, final boolean isMoveTo, final Folder actionFolder) {
+        return new FolderDestruction(target, folders, isDestructive, isBatch, showUndo,
+                isMoveTo ? R.id.move_folder : R.id.change_folder, actionFolder);
     }
 
     @Override
@@ -3228,7 +3261,7 @@
         Collection<FolderOperation> folderOps = new ArrayList<FolderOperation>();
         folderOps.add(new FolderOperation(toRemove, false));
         return new FolderDestruction(target, folderOps, isDestructive, isBatch,
-                showUndo, R.id.remove_folder);
+                showUndo, R.id.remove_folder, mFolder);
     }
 
     @Override
@@ -3315,7 +3348,7 @@
                 false, /* showActionIcon */
                 actionTextResourceId,
                 replaceVisibleToast,
-                new ToastBarOperation(1, 0, ToastBarOperation.ERROR, false));
+                new ToastBarOperation(1, 0, ToastBarOperation.ERROR, false, folder));
     }
 
     private ActionClickedListener getRetryClickedListener(final Folder folder) {
diff --git a/src/com/android/mail/ui/ConversationUpdater.java b/src/com/android/mail/ui/ConversationUpdater.java
index fe7f621..55511ac 100644
--- a/src/com/android/mail/ui/ConversationUpdater.java
+++ b/src/com/android/mail/ui/ConversationUpdater.java
@@ -23,7 +23,6 @@
 
 import com.android.mail.browse.ConfirmDialogFragment;
 import com.android.mail.browse.ConversationCursor;
-import com.android.mail.browse.ConversationItemView;
 import com.android.mail.browse.MessageCursor.ConversationMessage;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.ConversationInfo;
@@ -142,15 +141,17 @@
             boolean showUndo);
 
     /**
-     * Assign the target conversations to the given folders, and remove them from all other
-     * folders that they might be assigned to.
+     * Assign the target conversations to the given folders, and remove them from all other folders
+     * that they might be assigned to.
      * @param folders the folders to assign the conversations to.
      * @param target the conversations to act upon.
      * @param batch whether this is a batch operation
      * @param showUndo whether to show the undo bar
+     * @param isMoveTo <code>true</code> if this is a move operation, <code>false</code> if it is
+     *        some other type of folder change operation
      */
     public void assignFolder(Collection<FolderOperation> folders, Collection<Conversation> target,
-            boolean batch, boolean showUndo);
+            boolean batch, boolean showUndo, boolean isMoveTo);
 
     /**
      * Refreshes the conversation list, if one exists.
diff --git a/src/com/android/mail/ui/MultiFoldersSelectionDialog.java b/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
index 41b0778..cc95a48 100644
--- a/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
+++ b/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
@@ -30,7 +30,6 @@
 import com.android.mail.ui.FolderSelectorAdapter.FolderRow;
 import com.android.mail.utils.Utils;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
@@ -152,7 +151,8 @@
         switch (which) {
             case DialogInterface.BUTTON_POSITIVE:
                 if (mUpdater != null) {
-                    mUpdater.assignFolder(mOperations.values(), mTarget, mBatch, true);
+                    mUpdater.assignFolder(mOperations.values(), mTarget, mBatch,
+                            true /* showUndo */, false /* isMoveTo */);
                 }
                 break;
             case DialogInterface.BUTTON_NEGATIVE:
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index 44d7ed9..fc33b8d 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -608,7 +608,7 @@
                                     convList != null ? convList.getAnimatedAdapter() : null),
                             0,
                             Utils.convertHtmlToPlainText
-                                (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                (op.getDescription(mActivity.getActivityContext())),
                             true, /* showActionIcon */
                             R.string.undo,
                             true,  /* replaceVisibleToast */
@@ -622,7 +622,7 @@
                                 getUndoClickedListener(convList.getAnimatedAdapter()),
                                 0,
                                 Utils.convertHtmlToPlainText
-                                    (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                    (op.getDescription(mActivity.getActivityContext())),
                                 true, /* showActionIcon */
                                 R.string.undo,
                                 true,  /* replaceVisibleToast */
diff --git a/src/com/android/mail/ui/SingleFolderSelectionDialog.java b/src/com/android/mail/ui/SingleFolderSelectionDialog.java
index fd0d4eb..f7c5771 100644
--- a/src/com/android/mail/ui/SingleFolderSelectionDialog.java
+++ b/src/com/android/mail/ui/SingleFolderSelectionDialog.java
@@ -96,7 +96,7 @@
             // Remove the current folder and add the new folder.
             ops.add(new FolderOperation(mCurrentFolder, false));
             ops.add(new FolderOperation(folder, true));
-            mUpdater.assignFolder(ops, mTarget, mBatch, true);
+            mUpdater.assignFolder(ops, mTarget, mBatch, true /* showUndo */, true /* isMoveTo */);
             mDialog.dismiss();
         }
     }
diff --git a/src/com/android/mail/ui/SwipeableListView.java b/src/com/android/mail/ui/SwipeableListView.java
index 4048119..82d4d33 100644
--- a/src/com/android/mail/ui/SwipeableListView.java
+++ b/src/com/android/mail/ui/SwipeableListView.java
@@ -196,7 +196,8 @@
         final Context context = getContext();
         final ToastBarOperation undoOp;
 
-        undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO, false);
+        undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO, false /* batch */,
+                mFolder);
         Conversation conv = target.getConversation();
         target.getConversation().position = findConversation(target, conv);
         final AnimatedAdapter adapter = getAnimatedAdapter();
diff --git a/src/com/android/mail/ui/ToastBarOperation.java b/src/com/android/mail/ui/ToastBarOperation.java
index b56a94d..b47879f 100644
--- a/src/com/android/mail/ui/ToastBarOperation.java
+++ b/src/com/android/mail/ui/ToastBarOperation.java
@@ -33,19 +33,25 @@
     private final int mCount;
     private final boolean mBatch;
     private final int mType;
+    private final Folder mFolder;
 
     /**
      * Create a ToastBarOperation
      *
      * @param count Number of conversations this action would be applied to.
-     * @param menuId res id identifying the menu item tapped; used to determine
-     *            what action was performed
+     * @param menuId res id identifying the menu item tapped; used to determine what action was
+     *        performed
+     * @param operationFolder The {@link Folder} upon which the operation was run. This may be
+     *        <code>null</code>, but is required in {@link #getDescription(Context)} for certain
+     *        actions.
      */
-    public ToastBarOperation(int count, int menuId, int type, boolean batch) {
+    public ToastBarOperation(int count, int menuId, int type, boolean batch,
+            final Folder operationFolder) {
         mCount = count;
         mAction = menuId;
         mBatch = batch;
         mType = type;
+        mFolder = operationFolder;
     }
 
     public int getType() {
@@ -56,11 +62,12 @@
         return mBatch;
     }
 
-    public ToastBarOperation(Parcel in) {
+    public ToastBarOperation(final Parcel in, final ClassLoader loader) {
         mCount = in.readInt();
         mAction = in.readInt();
         mBatch = in.readInt() != 0;
         mType = in.readInt();
+        mFolder = in.readParcelable(loader);
     }
 
     @Override
@@ -69,35 +76,44 @@
         dest.writeInt(mAction);
         dest.writeInt(mBatch ? 1 : 0);
         dest.writeInt(mType);
+        dest.writeParcelable(mFolder, 0);
     }
 
-    public static final Creator<ToastBarOperation> CREATOR = new Creator<ToastBarOperation>() {
+    public static final ClassLoaderCreator<ToastBarOperation> CREATOR =
+            new ClassLoaderCreator<ToastBarOperation>() {
         @Override
-        public ToastBarOperation createFromParcel(Parcel source) {
-            return new ToastBarOperation(source);
+        public ToastBarOperation createFromParcel(final Parcel source) {
+            return createFromParcel(source, null);
         }
 
         @Override
-        public ToastBarOperation[] newArray(int size) {
+        public ToastBarOperation[] newArray(final int size) {
             return new ToastBarOperation[size];
         }
+
+        @Override
+        public ToastBarOperation createFromParcel(final Parcel source, final ClassLoader loader) {
+            return new ToastBarOperation(source, loader);
+        }
     };
 
     /**
      * Get a string description of the operation that will be performed
      * when the user taps the undo bar.
      */
-    public String getDescription(Context context, Folder folder) {
+    public String getDescription(Context context) {
         int resId = -1;
         switch (mAction) {
             case R.id.delete:
                 resId = R.plurals.conversation_deleted;
                 break;
             case R.id.remove_folder:
-                return context.getString(R.string.folder_removed, folder.name);
+                return context.getString(R.string.folder_removed, mFolder.name);
             case R.id.change_folder:
                 resId = R.plurals.conversation_folder_changed;
                 break;
+            case R.id.move_folder:
+                return context.getString(R.string.conversation_folder_moved, mFolder.name);
             case R.id.archive:
                 resId = R.plurals.conversation_archived;
                 break;
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index 4b45e3d..d022352 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -474,7 +474,7 @@
                             getUndoClickedListener(convList.getAnimatedAdapter()),
                             0,
                             Utils.convertHtmlToPlainText
-                                (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                (op.getDescription(mActivity.getActivityContext())),
                             true, /* showActionIcon */
                             R.string.undo,
                             true,  /* replaceVisibleToast */
@@ -486,7 +486,7 @@
                 if (convList != null) {
                     mToastBar.show(getUndoClickedListener(convList.getAnimatedAdapter()), 0,
                             Utils.convertHtmlToPlainText
-                                (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                (op.getDescription(mActivity.getActivityContext())),
                             true, /* showActionIcon */
                             R.string.undo, true, /* replaceVisibleToast */
                             op);