Add Empty trash/spam option

Bug: 4559378
Change-Id: I8dc5715a5f14f9fd6e8962ab665c4c25f3c64302
diff --git a/res/menu-sw600dp/conversation_list_menu.xml b/res/menu-sw600dp/conversation_list_menu.xml
index e54c963..ef35f84 100644
--- a/res/menu-sw600dp/conversation_list_menu.xml
+++ b/res/menu-sw600dp/conversation_list_menu.xml
@@ -15,6 +15,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
 
     <item android:id="@+id/compose"
@@ -37,6 +38,18 @@
         android:icon="@drawable/ic_menu_refresh_holo_light"
         android:alphabeticShortcut="@string/trigger_refresh_char" />
 
+    <!-- Available only in the trash folder, when the account supports emptying it -->
+    <item android:id="@+id/empty_trash"
+        android:title="@string/empty_trash"
+        android:showAsAction="never"
+        android:icon="@drawable/ic_menu_trash_holo_light" />
+
+    <!-- Available only in the spam folder, when the account supports emptying it -->
+    <item android:id="@+id/empty_spam"
+        android:title="@string/empty_spam"
+        android:showAsAction="never"
+        android:icon="@drawable/ic_menu_trash_holo_light" />
+
     <!-- Available for Folders with SUPPORTS_SETTINGS capability -->
     <item android:id="@+id/folder_options"
         android:title="@string/menu_folder_options"
diff --git a/res/menu/conversation_list_menu.xml b/res/menu/conversation_list_menu.xml
index 2a7d6e2..e2483b5 100644
--- a/res/menu/conversation_list_menu.xml
+++ b/res/menu/conversation_list_menu.xml
@@ -31,6 +31,18 @@
     android:icon="@drawable/ic_menu_search_holo_light"
     android:actionLayout="@layout/mail_actionbar_searchview" />
 
+    <!-- Available only in the trash folder, when the account supports emptying it -->
+    <item android:id="@+id/empty_trash"
+        android:title="@string/empty_trash"
+        android:showAsAction="never"
+        android:icon="@drawable/ic_menu_trash_holo_light" />
+
+    <!-- Available only in the spam folder, when the account supports emptying it -->
+    <item android:id="@+id/empty_spam"
+        android:title="@string/empty_spam"
+        android:showAsAction="never"
+        android:icon="@drawable/ic_menu_trash_holo_light" />
+
     <!-- Always available -->
     <item android:id="@+id/show_all_folders"
         android:title="@string/show_all_folders"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a1a02ec..c2782fd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -877,4 +877,9 @@
 	indicate that a sync is in progress.  [CHAR LIMIT=60] -->
     <string name="checking_for_mail">Checking for mail</string>
 
+    <!-- Conversation list screen overflow menu in trash folder [CHAR LIMIT=50]  -->
+    <string name="empty_trash">Empty trash</string>
+
+    <!-- Conversation list screen overflow menu in spam folder [CHAR LIMIT=50]  -->
+    <string name="empty_spam">Empty spam</string>
 </resources>
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index d9dfd46..eda54f8 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -74,7 +74,7 @@
  * caching for quick UI response. This is effectively a singleton class, as the cache is
  * implemented as a static HashMap.
  */
-public final class ConversationCursor implements Cursor, ConversationCursorMarkSeenListener {
+public final class ConversationCursor implements Cursor, ConversationCursorOperationListener {
 
     private static final boolean ENABLE_CONVERSATION_PRECACHING = true;
 
@@ -2060,11 +2060,13 @@
         }
     }
 
-    /**
-     * Marks all contents of this cursor as seen. This may have no effect with certain providers.
-     */
     @Override
     public void markContentsSeen() {
-        ConversationCursorMarkSeenListener.MarkSeenHelper.markContentsSeen(mUnderlyingCursor);
+        ConversationCursorOperationListener.OperationHelper.markContentsSeen(mUnderlyingCursor);
+    }
+
+    @Override
+    public void emptyFolder() {
+        ConversationCursorOperationListener.OperationHelper.emptyFolder(mUnderlyingCursor);
     }
 }
diff --git a/src/com/android/mail/browse/ConversationCursorMarkSeenListener.java b/src/com/android/mail/browse/ConversationCursorMarkSeenListener.java
deleted file mode 100644
index 0956859..0000000
--- a/src/com/android/mail/browse/ConversationCursorMarkSeenListener.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- *      Copyright (C) 2013 Google Inc.
- *      Licensed to 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.mail.browse;
-
-import android.database.Cursor;
-import android.database.CursorWrapper;
-
-public interface ConversationCursorMarkSeenListener {
-    /**
-     * Marks all contents of this cursor as seen.
-     */
-    void markContentsSeen();
-
-    public class MarkSeenHelper {
-        /**
-         * Invokes {@link ConversationCursorMarkSeenListener#markContentsSeen(Cursor)} on the
-         * specified {@link Cursor}, recursively calls {@link #markContentsSeen(Cursor)} on a
-         * wrapped cursor, or returns.
-         */
-        public static void markContentsSeen(final Cursor cursor) {
-            if (cursor == null) {
-                return;
-            }
-
-            if (cursor instanceof ConversationCursorMarkSeenListener) {
-                ((ConversationCursorMarkSeenListener) cursor).markContentsSeen();
-            } else if (cursor instanceof CursorWrapper) {
-                markContentsSeen(((CursorWrapper) cursor).getWrappedCursor());
-            }
-        }
-    }
-}
diff --git a/src/com/android/mail/browse/ConversationCursorOperationListener.java b/src/com/android/mail/browse/ConversationCursorOperationListener.java
new file mode 100644
index 0000000..1ca8116
--- /dev/null
+++ b/src/com/android/mail/browse/ConversationCursorOperationListener.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ *      Copyright (C) 2013 Google Inc.
+ *      Licensed to 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.mail.browse;
+
+import android.database.Cursor;
+import android.database.CursorWrapper;
+
+public interface ConversationCursorOperationListener {
+    /**
+     * Marks all contents of this cursor as seen.
+     */
+    void markContentsSeen();
+
+    /**
+     * Empties the folder of all messages, if possible.
+     */
+    void emptyFolder();
+
+    public class OperationHelper {
+        /**
+         * Invokes {@link ConversationCursorOperationListener#markContentsSeen(Cursor)} on the
+         * specified {@link Cursor}, recursively calls {@link #markContentsSeen(Cursor)} on a
+         * wrapped cursor, or returns.
+         */
+        public static void markContentsSeen(final Cursor cursor) {
+            if (cursor == null) {
+                return;
+            }
+
+            if (cursor instanceof ConversationCursorOperationListener) {
+                ((ConversationCursorOperationListener) cursor).markContentsSeen();
+            } else if (cursor instanceof CursorWrapper) {
+                markContentsSeen(((CursorWrapper) cursor).getWrappedCursor());
+            }
+        }
+
+        /**
+         * Invokes {@link ConversationCursorOperationListener#emptyFolder(Cursor)} on the
+         * specified {@link Cursor}, recursively calls {@link #emptyFolder(Cursor)} on a
+         * wrapped cursor, or returns.
+         */
+        public static void emptyFolder(final Cursor cursor) {
+            if (cursor == null) {
+                return;
+            }
+
+            if (cursor instanceof ConversationCursorOperationListener) {
+                ((ConversationCursorOperationListener) cursor).emptyFolder();
+            } else if (cursor instanceof CursorWrapper) {
+                emptyFolder(((CursorWrapper) cursor).getWrappedCursor());
+            }
+        }
+    }
+}
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index f602741..b6e37b7 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -284,6 +284,14 @@
          * removed when all providers support this capability
          */
         public static final int DISCARD_CONVERSATION_DRAFTS = 0x100000;
+        /**
+         * Whether the account supports emptying the trash folder
+         */
+        public static final int EMPTY_TRASH = 0x200000;
+        /**
+         * Whether the account supports emptying the spam folder
+         */
+        public static final int EMPTY_SPAM = 0x400000;
     }
 
     public static final class AccountColumns implements BaseColumns {
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index 6cf271f..3f48590 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -1069,6 +1069,10 @@
                     dialog.show();
                 }
                 break;
+            case R.id.empty_trash:
+            case R.id.empty_spam:
+                emptyFolder();
+                break;
             default:
                 handled = false;
                 break;
@@ -1076,6 +1080,10 @@
         return handled;
     }
 
+    private void emptyFolder() {
+        mConversationListCursor.emptyFolder();
+    }
+
     /**
      * Stand-in method overriden in OnePaneController for toggling the state
      * of the drawer.
diff --git a/src/com/android/mail/ui/MailActionBarView.java b/src/com/android/mail/ui/MailActionBarView.java
index 3fcda76..067fd20 100644
--- a/src/com/android/mail/ui/MailActionBarView.java
+++ b/src/com/android/mail/ui/MailActionBarView.java
@@ -53,6 +53,7 @@
 import com.android.mail.providers.UIProvider;
 import com.android.mail.providers.UIProvider.AccountCapabilities;
 import com.android.mail.providers.UIProvider.FolderCapabilities;
+import com.android.mail.providers.UIProvider.FolderType;
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.Utils;
@@ -97,6 +98,8 @@
     private MenuItem mSendFeedbackItem;
     private MenuItem mRefreshItem;
     private MenuItem mFolderSettingsItem;
+    private MenuItem mEmptyTrashItem;
+    private MenuItem mEmptySpamItem;
     private View mRefreshActionView;
     /** True if the current device is a tablet, false otherwise. */
     protected final boolean mIsOnTablet;
@@ -234,6 +237,8 @@
         mSendFeedbackItem = menu.findItem(R.id.feedback_menu_item);
         mRefreshItem = menu.findItem(R.id.refresh);
         mFolderSettingsItem = menu.findItem(R.id.folder_options);
+        mEmptyTrashItem = menu.findItem(R.id.empty_trash);
+        mEmptySpamItem = menu.findItem(R.id.empty_spam);
         return true;
     }
 
@@ -401,6 +406,16 @@
             mFolderSettingsItem.setVisible(mFolder != null
                     && mFolder.supportsCapability(FolderCapabilities.SUPPORTS_SETTINGS));
         }
+        if (mEmptyTrashItem != null) {
+            mEmptyTrashItem.setVisible(mAccount != null && mFolder != null
+                    && mAccount.supportsCapability(AccountCapabilities.EMPTY_TRASH)
+                    && mFolder.isTrash());
+        }
+        if (mEmptySpamItem != null) {
+            mEmptySpamItem.setVisible(mAccount != null && mFolder != null
+                    && mAccount.supportsCapability(AccountCapabilities.EMPTY_SPAM)
+                    && mFolder.isType(FolderType.SPAM));
+        }
 
         switch (mMode) {
             case ViewMode.CONVERSATION: