Merge "Import translations. DO NOT MERGE" into jb-ub-mail-ur9
diff --git a/res/menu/conversation_list_selection_actions_menu.xml b/res/menu/conversation_list_selection_actions_menu.xml
index c8823ae..d97d6ab 100644
--- a/res/menu/conversation_list_selection_actions_menu.xml
+++ b/res/menu/conversation_list_selection_actions_menu.xml
@@ -53,17 +53,17 @@
         android:icon="@drawable/trash"
         android:visible="false" />
 
-    <!-- Only one of mark read or mark unread is shown. Both of these are set as always. -->
+    <!-- Only one of mark read or mark unread is shown. -->
     <item
         android:id="@+id/read"
         android:title="@string/mark_read"
-        android:showAsAction="always"
+        android:showAsAction="ifRoom"
         android:icon="@drawable/ic_menu_mark_read_holo_light" />
 
     <item
         android:id="@+id/unread"
         android:title="@string/mark_unread"
-        android:showAsAction="always"
+        android:showAsAction="ifRoom"
         android:icon="@drawable/ic_menu_mark_unread_holo_light" />
 
     <item
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8754154..58a56a6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -838,33 +838,38 @@
     <string name="silent_ringtone">Silent</string>
 
     <!-- Settings screen, preference name for archive vs. delete [CHAR LIMIT=50] -->
-    <string name="preference_archive_vs_delete_title">Remove action</string>
+    <string name="preference_removal_action_title">Archive &amp; delete actions</string>
     <!-- Options to select from for whether to have archive or delete as the remove action [CHAR LIMIT=50] -->
-    <string-array name="prefEntries_archive_vs_delete">
-        <item>Archive conversations</item>
-        <item>Delete conversations</item>
+    <string-array name="prefEntries_removal_action">
+        <item>Show archive only</item>
+        <item>Show delete only</item>
+        <item>Show archive &amp; delete</item>
     </string-array>
     <!-- Description of currently selected option of whether to use archive or delete as remove action [CHAR LIMIT=200] -->
-    <string-array name="prefSummaries_archive_vs_delete_summary">
-        <item>Archive rather than delete conversations</item>
-        <item>Delete rather than archive conversations</item>
+    <string-array name="prefSummaries_removal_action_summary">
+        <item>Show archive only</item>
+        <item>Show delete only</item>
+        <item>Show archive &amp; delete</item>
     </string-array>
-    <string-array translatable="false" name="prefValues_archive_vs_delete">
+    <string-array translatable="false" name="prefValues_removal_action">
         <item>archive</item>
         <item>delete</item>
+        <item>archive-and-delete</item>
     </string-array>
     <!-- Dialog title for the choosing whether to use archive or delete as remove action [CHAR LIMIT=150] -->
-    <string name="prefDialogTitle_archive_vs_delete">Remove action</string>
+    <string name="prefDialogTitle_removal_action">Archive &amp; delete actions</string>
     <!-- The default value -->
-    <string translatable="false" name="prefDefault_archive_vs_delete">archive</string>
+    <string translatable="false" name="prefDefault_removal_action">archive</string>
 
     <!--  Settings screen, Reply to all default setting title  [CHAR LIMIT=30] -->
     <string name="preferences_default_reply_all_title">Reply all</string>
     <!--  Settings screen, Reply to all default setting summary [CHAR LIMIT=70] -->
     <string name="preferences_default_reply_all_summary">Use as default for message replies</string>
 
-    <!-- Preference name for swipe action [CHAR LIMIT=100]-->
-    <string name="preference_swipe_title">Swipe to remove</string>
+    <!-- Preference name for swipe action when action is archive [CHAR LIMIT=100]-->
+    <string name="preference_swipe_title_archive">Swipe to archive</string>
+    <!-- Preference name for swipe action when action is delete [CHAR LIMIT=100]-->
+    <string name="preference_swipe_title_delete">Swipe to delete</string>
     <!-- Preference description swiping in conversation list option [CHAR LIMIT=100] -->
     <string name="preference_swipe_description">In conversation list</string>
 
diff --git a/src/com/android/mail/browse/SelectedConversationsActionMenu.java b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
index 5fd902b..16cfa8d 100644
--- a/src/com/android/mail/browse/SelectedConversationsActionMenu.java
+++ b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
@@ -458,7 +458,7 @@
             discardDrafts.setVisible(showDiscardDrafts);
         }
 
-        MailActionBarView.reorderMenu(mContext, menu);
+        MailActionBarView.reorderMenu(mContext, mAccount, menu);
 
         return true;
     }
diff --git a/src/com/android/mail/preferences/FolderPreferences.java b/src/com/android/mail/preferences/FolderPreferences.java
index 4da2089..e058613 100644
--- a/src/com/android/mail/preferences/FolderPreferences.java
+++ b/src/com/android/mail/preferences/FolderPreferences.java
@@ -249,10 +249,11 @@
 
     public Set<String> getNotificationActions(final Account account) {
         final boolean supportsArchiveRemoveLabel =
-                account.supportsCapability(AccountCapabilities.ARCHIVE)
-                && (mFolder.supportsCapability(FolderCapabilities.ARCHIVE)
-                || mFolder.supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION));
-        final boolean preferDelete = MailPrefs.get(getContext()).getPreferDelete();
+                mFolder.supportsCapability(FolderCapabilities.ARCHIVE)
+                || mFolder.supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION);
+        final boolean preferDelete = MailPrefs.RemovalActions.DELETE.equals(
+                MailPrefs.get(getContext()).getRemovalAction(
+                        account.supportsCapability(AccountCapabilities.ARCHIVE)));
         final NotificationActionType destructiveActionType =
                 supportsArchiveRemoveLabel && !preferDelete ?
                         NotificationActionType.ARCHIVE_REMOVE_LABEL : NotificationActionType.DELETE;
diff --git a/src/com/android/mail/preferences/MailPrefs.java b/src/com/android/mail/preferences/MailPrefs.java
index ff4e0f8..cad7ef5 100644
--- a/src/com/android/mail/preferences/MailPrefs.java
+++ b/src/com/android/mail/preferences/MailPrefs.java
@@ -59,9 +59,9 @@
         public static final String CONVERSATION_LIST_SWIPE = "conversation-list-swipe";
 
         /**
-         * A boolean indicating whether the user prefers delete or archive.
+         * A string indicating the user's removal action preference.
          */
-        public static final String PREFER_DELETE = "prefer-delete";
+        public static final String REMOVAL_ACTION = "removal-action";
 
         /** Hidden preference used to cache the active notification set */
         private static final String CACHED_ACTIVE_NOTIFICATION_SET =
@@ -71,7 +71,7 @@
                 new ImmutableSet.Builder<String>()
                 .add(DEFAULT_REPLY_ALL)
                 .add(CONVERSATION_LIST_SWIPE)
-                .add(PREFER_DELETE)
+                .add(REMOVAL_ACTION)
                 .build();
 
     }
@@ -82,6 +82,12 @@
         public static final String DISABLED = "disabled";
     }
 
+    public static final class RemovalActions {
+        public static final String ARCHIVE = "archive";
+        public static final String DELETE = "delete";
+        public static final String ARCHIVE_AND_DELETE = "archive-and-delete";
+    }
+
     public static MailPrefs get(Context c) {
         if (sInstance == null) {
             sInstance = new MailPrefs(c);
@@ -157,15 +163,23 @@
     }
 
     /**
-     * Gets a boolean indicating whether delete is preferred over archive.
+     * Returns a string indicating the preferred removal action.
+     * Should be one of the {@link RemovalActions}.
      */
-    public boolean getPreferDelete() {
+    public String getRemovalAction(final boolean supportsArchive) {
+        final String defaultAction = supportsArchive
+                ? RemovalActions.ARCHIVE : RemovalActions.DELETE;
+
         final SharedPreferences sharedPreferences = getSharedPreferences();
-        return sharedPreferences.getBoolean(PreferenceKeys.PREFER_DELETE, false);
+        return sharedPreferences.getString(PreferenceKeys.REMOVAL_ACTION, defaultAction);
     }
 
-    public void setPreferDelete(final boolean preferDelete) {
-        getEditor().putBoolean(PreferenceKeys.PREFER_DELETE, preferDelete).apply();
+    /**
+     * Sets the removal action preference.
+     * @param removalAction The preferred {@link RemovalActions}.
+     */
+    public void setRemovalAction(final String removalAction) {
+        getEditor().putString(PreferenceKeys.REMOVAL_ACTION, removalAction).apply();
         MailIntentService.broadcastBackupDataChanged(getContext());
     }
 
@@ -191,7 +205,7 @@
      */
     public int getConversationListSwipeActionInteger(final boolean allowArchive) {
         final boolean swipeEnabled = getIsConversationListSwipeEnabled();
-        final boolean archive = !getPreferDelete() && allowArchive;
+        final boolean archive = !RemovalActions.DELETE.equals(getRemovalAction(allowArchive));
 
         if (swipeEnabled) {
             return archive ? UIProvider.Swipe.ARCHIVE : UIProvider.Swipe.DELETE;
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index d976562..822e21f 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -652,16 +652,16 @@
             mDrawerObservers.notifyChanged();
             return;
         }
-
-        if (nextFolder != null) {
-            preloadConvList(nextAccount, nextFolder);
-        }
         // If there are no new folders or accounts to switch to, just close the drawer
         if (!hasNewFolderOrAccount) {
             mDrawerContainer.closeDrawers();
             return;
         }
-
+        // Otherwise, start preloading the conversation list for the new folder.
+        if (nextFolder != null) {
+            preloadConvList(nextAccount, nextFolder);
+        }
+        // Remember if the conversation list view is animating
         final ConversationListFragment conversationList = getConversationListFragment();
         if (conversationList != null) {
             mListViewForAnimating = conversationList.getListView();
diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java
index e4759e3..4f83e71 100644
--- a/src/com/android/mail/ui/AbstractConversationViewFragment.java
+++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java
@@ -838,7 +838,12 @@
      */
     public void onConversationTransformed() {
         mHasConversationBeenTransformed = true;
-        mActivity.invalidateOptionsMenu();
+        mHandler.post(new FragmentRunnable("invalidateOptionsMenu") {
+            @Override
+            public void go() {
+                mActivity.invalidateOptionsMenu();
+            }
+        });
     }
 
     /**
diff --git a/src/com/android/mail/ui/ConversationListView.java b/src/com/android/mail/ui/ConversationListView.java
index 16fc4ea..c077b1c 100644
--- a/src/com/android/mail/ui/ConversationListView.java
+++ b/src/com/android/mail/ui/ConversationListView.java
@@ -1,5 +1,8 @@
 package com.android.mail.ui;
 
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -48,6 +51,7 @@
 
     private View mSyncTriggerBar;
     private View mSyncProgressBar;
+    private AnimatorListenerAdapter mSyncProgressBarFadeListener;
     private SwipeableListView mListView;
 
     // Whether to ignore events in {#dispatchTouchEvent}.
@@ -110,10 +114,20 @@
 
         // Calculate distance threshold for triggering a sync based on
         // screen height.  Apply a min and max cutoff.
-        float threshold = ((float) displayMetrics.heightPixels) / mDensity / 2.5f;
+        float threshold = (displayMetrics.heightPixels) / mDensity / 2.5f;
         mDistanceToTriggerSyncDp = Math.max(
                 Math.min(threshold, MAX_DISTANCE_TO_TRIGGER_SYNC),
                 MIN_DISTANCE_TO_TRIGGER_SYNC);
+
+        mSyncProgressBarFadeListener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator arg0) {
+                // Even though alpha is set to 0, still need to set visiblity to
+                // GONE, otherwise the progressbar animation continues to get drawn
+                // even though it's not visible.
+                mSyncProgressBar.setVisibility(GONE);
+            }
+        };
     }
 
     protected void setFolderController(FolderController folderController) {
@@ -275,7 +289,8 @@
             LogUtils.i(LOG_TAG, "ConversationListView hide sync status bar");
             // Hide both the sync progress bar and sync trigger bar
             mSyncProgressBar.animate().alpha(0f)
-                    .setDuration(SYNC_STATUS_BAR_FADE_DURATION_IN_MILLIS);
+                    .setDuration(SYNC_STATUS_BAR_FADE_DURATION_IN_MILLIS)
+                    .setListener(mSyncProgressBarFadeListener);
             mSyncTriggerBar.setVisibility(GONE);
             mIsSyncing = false;
         }
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index b3c8999..b43983f 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -1164,9 +1164,14 @@
         @SuppressWarnings("unused")
         @JavascriptInterface
         public void onMessageTransform(String messageDomId, String transformText) {
-            LogUtils.i(LOG_TAG, "TRANSFORM: (%s) %s", messageDomId, transformText);
-            mMessageTransforms.put(messageDomId, transformText);
-            onConversationTransformed();
+            try {
+                LogUtils.i(LOG_TAG, "TRANSFORM: (%s) %s", messageDomId, transformText);
+                mMessageTransforms.put(messageDomId, transformText);
+                onConversationTransformed();
+            } catch (Throwable t) {
+                LogUtils.e(LOG_TAG, t, "Error in MailJsBridge.onMessageTransform");
+                return;
+            }
         }
     }
 
diff --git a/src/com/android/mail/ui/MailActionBarView.java b/src/com/android/mail/ui/MailActionBarView.java
index 2ed3870..a935573 100644
--- a/src/com/android/mail/ui/MailActionBarView.java
+++ b/src/com/android/mail/ui/MailActionBarView.java
@@ -429,7 +429,7 @@
                 // is added.
                 setConversationModeOptions(menu);
                 // We want to use the user's preferred menu order here
-                reorderMenu(getContext(), menu);
+                reorderMenu(getContext(), mAccount, menu);
                 break;
             case ViewMode.CONVERSATION_LIST:
                 // Show compose and search based on the account
@@ -451,8 +451,13 @@
      * Reorders the specified {@link Menu}, taking into account the user's Archive/Delete
      * preference.
      */
-    public static void reorderMenu(final Context context, final Menu menu) {
-        final boolean preferDelete = MailPrefs.get(context).getPreferDelete();
+    public static void reorderMenu(final Context context, final Account account, final Menu menu) {
+        final String removalAction = MailPrefs.get(context).getRemovalAction(
+                account.supportsCapability(AccountCapabilities.ARCHIVE));
+        final boolean showArchive = MailPrefs.RemovalActions.ARCHIVE.equals(removalAction) ||
+                MailPrefs.RemovalActions.ARCHIVE_AND_DELETE.equals(removalAction);
+        final boolean showDelete = MailPrefs.RemovalActions.DELETE.equals(removalAction) ||
+                MailPrefs.RemovalActions.ARCHIVE_AND_DELETE.equals(removalAction);
 
         // Do a first pass to extract necessary information on what is safe to move to the overflow
         boolean archiveVisibleEnabled = false;
@@ -474,15 +479,31 @@
             final MenuItem menuItem = menu.getItem(i);
             final int itemId = menuItem.getItemId();
 
-            if (preferDelete && deleteVisibleEnabled) {
+            if (!showArchive && deleteVisibleEnabled) {
                 if (itemId == R.id.archive || itemId == R.id.remove_folder) {
                     menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                 }
-            } else if (!preferDelete && archiveVisibleEnabled) {
+            }
+
+            if (!showDelete && archiveVisibleEnabled) {
                 if (itemId == R.id.delete || itemId == R.id.discard_drafts) {
                     menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                 }
             }
+
+            if (showArchive && archiveVisibleEnabled && showDelete && deleteVisibleEnabled) {
+                if (itemId == R.id.move_to) {
+                    menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+                }
+            }
+
+            // TODO(skennedy) Refactor the above into this switch
+            switch (itemId) {
+                case R.id.change_folder:
+                    menuItem.setVisible(account
+                            .supportsCapability(AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV));
+                    break;
+            }
         }
     }