111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira/* 211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * Copyright (C) 2010 Google Inc. 311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * Licensed to The Android Open Source Project. 411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * 511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * you may not use this file except in compliance with the License. 711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * You may obtain a copy of the License at 811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * 911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 1011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * 1111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * Unless required by applicable law or agreed to in writing, software 1211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 1311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * See the License for the specific language governing permissions and 1511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * limitations under the License. 1611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira */ 1711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 1811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereirapackage com.android.mail.browse; 1911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 20bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport android.content.Context; 21a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blankimport android.net.Uri; 22dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedyimport android.os.AsyncTask; 2352882ff08fe9420fe2dbb3f681545a330222e9c8Andrew Sappersteinimport android.support.v7.view.ActionMode; 24bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport android.view.Menu; 25bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport android.view.MenuInflater; 26bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport android.view.MenuItem; 27a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blankimport android.widget.Toast; 28bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook 2911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereiraimport com.android.mail.R; 30042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huangimport com.android.mail.analytics.Analytics; 3130d2d329418045d1f6af60877fa14183ec28ead4Mindy Pereiraimport com.android.mail.providers.Account; 327c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwalimport com.android.mail.providers.AccountObserver; 3311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereiraimport com.android.mail.providers.Conversation; 344f166dead6323b6fd21c76cef66174c6cd4bf11cMindy Pereiraimport com.android.mail.providers.Folder; 35a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blankimport com.android.mail.providers.MailAppProvider; 36efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereiraimport com.android.mail.providers.Settings; 37f98b318572750dae998a55a60199598933770b68Mindy Pereiraimport com.android.mail.providers.UIProvider; 38ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrookimport com.android.mail.providers.UIProvider.AccountCapabilities; 39cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blankimport com.android.mail.providers.UIProvider.ConversationColumns; 40bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.providers.UIProvider.FolderCapabilities; 419ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereiraimport com.android.mail.providers.UIProvider.FolderType; 42531488ed848766708252a5fdc01c4ecf0fd167d1Vikram Aggarwalimport com.android.mail.ui.ControllableActivity; 43ec0fa48764bede0772e9c711f3e33361b62f3608Jin Caoimport com.android.mail.ui.ConversationCheckedSet; 44a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwalimport com.android.mail.ui.ConversationListCallbacks; 451ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport com.android.mail.ui.ConversationSetObserver; 46531488ed848766708252a5fdc01c4ecf0fd167d1Vikram Aggarwalimport com.android.mail.ui.ConversationUpdater; 47a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blankimport com.android.mail.ui.DestructiveAction; 48dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedyimport com.android.mail.ui.FolderOperation; 499eb1c9a76a400f84c002b58c831119119ebf4870Mark Weiimport com.android.mail.ui.FolderSelectionDialog; 50b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 5111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereiraimport com.android.mail.utils.LogUtils; 52efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereiraimport com.android.mail.utils.Utils; 5311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereiraimport com.google.common.annotations.VisibleForTesting; 54dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedyimport com.google.common.collect.Lists; 5511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 5611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereiraimport java.util.Collection; 57dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedyimport java.util.List; 5811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 5911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira/** 6011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * A component that displays a custom view for an {@code ActionBar}'s {@code 6111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * ContextMode} specific to operating on a set of conversations. 6211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira */ 6311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereirapublic class SelectedConversationsActionMenu implements ActionMode.Callback, 64d503df4f0c31bbf842c6a1d3cba18df8c074bf67Vikram Aggarwal ConversationSetObserver { 6511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 66b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 6711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 6811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira /** 6911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * The set of conversations to display the menu for. 7011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira */ 71ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao protected final ConversationCheckedSet mCheckedSet; 7211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 73a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal private final ControllableActivity mActivity; 74a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal private final ConversationListCallbacks mListController; 75cd8bf0a4c081f95ac8666025adb85d4908c2018aVikram Aggarwal /** 76cd8bf0a4c081f95ac8666025adb85d4908c2018aVikram Aggarwal * Context of the activity. A dialog requires the context of an activity rather than the global 77cd8bf0a4c081f95ac8666025adb85d4908c2018aVikram Aggarwal * root context of the process. So mContext = mActivity.getApplicationContext() will fail. 78cd8bf0a4c081f95ac8666025adb85d4908c2018aVikram Aggarwal */ 7911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira private final Context mContext; 8011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 8111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @VisibleForTesting 824f4782bcc53e13b30f1fd417beb1a6c04a54faedVikram Aggarwal private ActionMode mActionMode; 8311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 8411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira private boolean mActivated = false; 8511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 86531488ed848766708252a5fdc01c4ecf0fd167d1Vikram Aggarwal /** Object that can update conversation state on our behalf. */ 87531488ed848766708252a5fdc01c4ecf0fd167d1Vikram Aggarwal private final ConversationUpdater mUpdater; 8830d2d329418045d1f6af60877fa14183ec28ead4Mindy Pereira 897c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private Account mAccount; 90d92e9f3d45cfedd3ebfedcf0805283007053e091Mindy Pereira 91531488ed848766708252a5fdc01c4ecf0fd167d1Vikram Aggarwal private final Folder mFolder; 924f166dead6323b6fd21c76cef66174c6cd4bf11cMindy Pereira 9314f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira private AccountObserver mAccountObserver; 9407118a01f7183645957010779222b84930f75b4eMindy Pereira 95512821c11d89d49908f3cfdee0b582601f500f3dJin Cao private MenuItem mDiscardOutboxMenuItem; 96512821c11d89d49908f3cfdee0b582601f500f3dJin Cao 977704d79def5e5f36a1cbe22fbbe6e9520503899cVikram Aggarwal public SelectedConversationsActionMenu( 98ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao ControllableActivity activity, ConversationCheckedSet checkedSet, Folder folder) { 9911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira mActivity = activity; 100a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal mListController = activity.getListHandler(); 101ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedSet = checkedSet; 10214f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira mAccountObserver = new AccountObserver() { 10314f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira @Override 10414f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira public void onChanged(Account newAccount) { 10514f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira mAccount = newAccount; 10614f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira } 10714f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira }; 1087c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mAccount = mAccountObserver.initialize(activity.getAccountController()); 1094f166dead6323b6fd21c76cef66174c6cd4bf11cMindy Pereira mFolder = folder; 11004dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal mContext = mActivity.getActivityContext(); 11154f120f6ada40c7191811dfff99b151e9e192c78mindyp mUpdater = activity.getConversationUpdater(); 112e8a85328eadff76fcd78141f1343bde0a1cd27e7Vikram Aggarwal } 113e8a85328eadff76fcd78141f1343bde0a1cd27e7Vikram Aggarwal 114a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao public boolean onActionItemClicked(MenuItem item) { 115a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao return onActionItemClicked(mActionMode, item); 116a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao } 117a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao 11811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 11911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 12011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira boolean handled = true; 1218937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira // If the user taps a new menu item, commit any existing destructive actions. 122a8e4318bb9921e2ec6045c5f7187a4b78c55fe10Vikram Aggarwal mListController.commitDestructiveActions(true); 1232b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final int itemId = item.getItemId(); 124042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 1252b55549d4fbe25e91f673a0727fc89ff755d9327Andy Huang Analytics.getInstance().sendMenuItemEvent(Analytics.EVENT_CATEGORY_MENU_ITEM, itemId, 1262b55549d4fbe25e91f673a0727fc89ff755d9327Andy Huang "cab_mode", 0); 127042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 128f55863727de2bb15f1906944bbc88c82703a3affJin Cao UndoCallback undoCallback = null; // not applicable here (yet) 1292b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (itemId == R.id.delete) { 1302b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy LogUtils.i(LOG_TAG, "Delete selected from CAB menu"); 131f55863727de2bb15f1906944bbc88c82703a3affJin Cao performDestructiveAction(R.id.delete, undoCallback); 1322b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.discard_drafts) { 133512821c11d89d49908f3cfdee0b582601f500f3dJin Cao LogUtils.i(LOG_TAG, "Discard drafts selected from CAB menu"); 134f55863727de2bb15f1906944bbc88c82703a3affJin Cao performDestructiveAction(R.id.discard_drafts, undoCallback); 135512821c11d89d49908f3cfdee0b582601f500f3dJin Cao } else if (itemId == R.id.discard_outbox) { 136512821c11d89d49908f3cfdee0b582601f500f3dJin Cao LogUtils.i(LOG_TAG, "Discard outbox selected from CAB menu"); 137512821c11d89d49908f3cfdee0b582601f500f3dJin Cao performDestructiveAction(R.id.discard_outbox, undoCallback); 1382b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.archive) { 1392b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy LogUtils.i(LOG_TAG, "Archive selected from CAB menu"); 140f55863727de2bb15f1906944bbc88c82703a3affJin Cao performDestructiveAction(R.id.archive, undoCallback); 1412b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.remove_folder) { 142ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao destroy(R.id.remove_folder, mCheckedSet.values(), 143ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mUpdater.getDeferredRemoveFolder(mCheckedSet.values(), mFolder, true, 144f55863727de2bb15f1906944bbc88c82703a3affJin Cao true, true, undoCallback)); 1452b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.mute) { 146ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao destroy(R.id.mute, mCheckedSet.values(), mUpdater.getBatchAction(R.id.mute, 147f55863727de2bb15f1906944bbc88c82703a3affJin Cao undoCallback)); 1482b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.report_spam) { 149ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao destroy(R.id.report_spam, mCheckedSet.values(), 150f55863727de2bb15f1906944bbc88c82703a3affJin Cao mUpdater.getBatchAction(R.id.report_spam, undoCallback)); 1512b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.mark_not_spam) { 1522b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Currently, since spam messages are only shown in list with other spam messages, 1532b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // marking a message not as spam is a destructive action 1542b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy destroy (R.id.mark_not_spam, 155ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedSet.values(), mUpdater.getBatchAction(R.id.mark_not_spam, 156f55863727de2bb15f1906944bbc88c82703a3affJin Cao undoCallback)) ; 1572b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.report_phishing) { 1582b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy destroy(R.id.report_phishing, 159ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedSet.values(), mUpdater.getBatchAction(R.id.report_phishing, 160f55863727de2bb15f1906944bbc88c82703a3affJin Cao undoCallback)); 1612b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.read) { 1622b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy markConversationsRead(true); 1632b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.unread) { 1642b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy markConversationsRead(false); 1652b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.star) { 1662b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy starConversations(true); 167a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao } else if (itemId == R.id.toggle_read_unread) { 168a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao if (mActionMode != null) { 169a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao markConversationsRead(mActionMode.getMenu().findItem(R.id.read).isVisible()); 170a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao } 1712b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.remove_star) { 1722b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (mFolder.isType(UIProvider.FolderType.STARRED)) { 1732b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy LogUtils.d(LOG_TAG, "We are in a starred folder, removing the star"); 174f55863727de2bb15f1906944bbc88c82703a3affJin Cao performDestructiveAction(R.id.remove_star, undoCallback); 1752b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else { 1762b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy LogUtils.d(LOG_TAG, "Not in a starred folder."); 1772b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy starConversations(false); 1782b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } 1796c570db71b8adc43d7dc2f31e6fa63cf50c1426eAndrew Sapperstein } else if (itemId == R.id.move_to || itemId == R.id.change_folders) { 1802b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy boolean cantMove = false; 1812b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Account acct = mAccount; 1822b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Special handling for virtual folders 1832b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (mFolder.supportsCapability(FolderCapabilities.IS_VIRTUAL)) { 1842b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Uri accountUri = null; 185ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao for (Conversation conv: mCheckedSet.values()) { 1862b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (accountUri == null) { 1872b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy accountUri = conv.accountUri; 1882b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (!accountUri.equals(conv.accountUri)) { 1892b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Tell the user why we can't do this 1902b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Toast.makeText(mContext, R.string.cant_move_or_change_labels, 1912b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Toast.LENGTH_LONG).show(); 1922b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy cantMove = true; 1932b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy return handled; 194a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank } 195a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank } 196a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank if (!cantMove) { 1972b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Get the actual account here, so that we display its folders in the dialog 1982b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy acct = MailAppProvider.getAccountFromAccountUri(accountUri); 1992b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } 2002b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } 2012b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (!cantMove) { 2022b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final FolderSelectionDialog dialog = FolderSelectionDialog.getInstance( 203ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao acct, mCheckedSet.values(), true, mFolder, 2042b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy item.getItemId() == R.id.move_to); 2052b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (dialog != null) { 2062a4be2459962700e1a38ba897de5d2f5913412f5Tony Mantler dialog.show(mActivity.getFragmentManager(), null); 2072b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } 2082b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } 2092b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.move_to_inbox) { 2102b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy new AsyncTask<Void, Void, Folder>() { 2112b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy @Override 2122b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy protected Folder doInBackground(final Void... params) { 2132b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Get the "move to" inbox 2142b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy return Utils.getFolder(mContext, mAccount.settings.moveToInbox, 2152b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy true /* allowHidden */); 216a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493Marc Blank } 217dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedy 2182b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy @Override 2192b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy protected void onPostExecute(final Folder moveToInbox) { 2202b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final List<FolderOperation> ops = Lists.newArrayListWithCapacity(1); 2212b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Add inbox 2222b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ops.add(new FolderOperation(moveToInbox, true)); 223ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mUpdater.assignFolder(ops, mCheckedSet.values(), true, 2242b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy true /* showUndo */, false /* isMoveTo */); 22504dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal } 2262b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy }.execute((Void[]) null); 2272b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.mark_important) { 2282b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy markConversationsImportant(true); 2292b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (itemId == R.id.mark_not_important) { 2302b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (mFolder.supportsCapability(UIProvider.FolderCapabilities.ONLY_IMPORTANT)) { 231f55863727de2bb15f1906944bbc88c82703a3affJin Cao performDestructiveAction(R.id.mark_not_important, undoCallback); 2322b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else { 2332b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy markConversationsImportant(false); 2342b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } 2352b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else { 2362b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy handled = false; 23711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 23811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira return handled; 23911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 24011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 241ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal /** 242ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal * Clear the selection and perform related UI changes to keep the state consistent. 243ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal */ 244ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao private void clearChecked() { 245ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedSet.clear(); 246ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal } 247ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal 24804dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal /** 24904dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal * Update the underlying list adapter and redraw the menus if necessary. 25004dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal */ 25104dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal private void updateSelection() { 2524f4782bcc53e13b30f1fd417beb1a6c04a54faedVikram Aggarwal mUpdater.refreshConversationList(); 25304dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal if (mActionMode != null) { 25404dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal // Calling mActivity.invalidateOptionsMenu doesn't have the correct behavior, since 25504dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal // the action mode is not refreshed when activity's options menu is invalidated. 25604dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal // Since we need to refresh our own menu, it is easy to call onPrepareActionMode 25704dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal // directly. 25804dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal onPrepareActionMode(mActionMode, mActionMode.getMenu()); 25904dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal } 26004dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal } 26104dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal 262f55863727de2bb15f1906944bbc88c82703a3affJin Cao private void performDestructiveAction(final int action, UndoCallback undoCallback) { 263ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final Collection<Conversation> conversations = mCheckedSet.values(); 2646cadbfce032c5f8d61c873d91989bff1fb7cc4e5Vikram Aggarwal final Settings settings = mAccount.settings; 265121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang final boolean showDialog; 266121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang // no confirmation dialog by default unless user preference or common sense dictates one 267121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang if (action == R.id.discard_drafts) { 268121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang // drafts are lost forever, so always confirm 269121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang showDialog = true; 270121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang } else if (settings != null && (action == R.id.archive || action == R.id.delete)) { 271121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang showDialog = (action == R.id.delete) ? settings.confirmDelete : settings.confirmArchive; 272121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang } else { 273121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang showDialog = false; 274121c8b877090e780b4a16d5a14507c3649e61d7fAndy Huang } 275efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira if (showDialog) { 276f55863727de2bb15f1906944bbc88c82703a3affJin Cao mUpdater.makeDialogListener(action, true /* fromSelectedSet */, null /* undoCallback */); 277ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook final int resId; 2782b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (action == R.id.delete) { 2792b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy resId = R.plurals.confirm_delete_conversation; 2802b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (action == R.id.discard_drafts) { 2812b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy resId = R.plurals.confirm_discard_drafts_conversation; 2822b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else { 2832b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy resId = R.plurals.confirm_archive_conversation; 284ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook } 2856cadbfce032c5f8d61c873d91989bff1fb7cc4e5Vikram Aggarwal final CharSequence message = Utils.formatPlural(mContext, resId, conversations.size()); 2866cadbfce032c5f8d61c873d91989bff1fb7cc4e5Vikram Aggarwal final ConfirmDialogFragment c = ConfirmDialogFragment.newInstance(message); 287b8c3171710b7f97247fd0c841ce95f5f515ef576Vikram Aggarwal c.displayDialog(mActivity.getFragmentManager()); 288efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira } else { 2896cadbfce032c5f8d61c873d91989bff1fb7cc4e5Vikram Aggarwal // No need to show the dialog, just make a destructive action and destroy the 2906cadbfce032c5f8d61c873d91989bff1fb7cc4e5Vikram Aggarwal // selected set immediately. 291b8c3171710b7f97247fd0c841ce95f5f515ef576Vikram Aggarwal // TODO(viki): Stop using the deferred action here. Use the registered action. 292f55863727de2bb15f1906944bbc88c82703a3affJin Cao destroy(action, conversations, mUpdater.getDeferredBatchAction(action, undoCallback)); 29307118a01f7183645957010779222b84930f75b4eMindy Pereira } 29407118a01f7183645957010779222b84930f75b4eMindy Pereira } 29507118a01f7183645957010779222b84930f75b4eMindy Pereira 29684fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal /** 29784fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal * Destroy these conversations through the conversation updater 29884fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal * @param actionId the ID of the action: R.id.archive, R.id.delete, ... 29984fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal * @param target conversations to destroy 30084fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal * @param action the action that performs the destruction 30184fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal */ 30284fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal private void destroy(int actionId, final Collection<Conversation> target, 30384fe99431df3b989dff9b363562f09fd2757b63cVikram Aggarwal final DestructiveAction action) { 304193e05a8c38b87c400ac594b53b54eb211d35602Alice Yang LogUtils.i(LOG_TAG, "About to remove %d converations", target.size()); 305caaeed3837316175111bb16e6b60aeb0d523debfScott Kennedy mUpdater.delete(actionId, target, action, true); 306efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira } 307efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira 3080e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal /** 3090e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * Marks the read state of currently selected conversations (<b>and</b> the backing storage) 3100e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * to the value provided here. 3110e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * @param read is true if the conversations are to be marked as read, false if they are to be 3120e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * marked unread. 3130e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal */ 314febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira private void markConversationsRead(boolean read) { 315ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final Collection<Conversation> targets = mCheckedSet.values(); 31666bc2aaf76bb0dfa4fc38f8fcbaaf9e413e321ddVikram Aggarwal // The conversations are marked read but not viewed. 31766bc2aaf76bb0dfa4fc38f8fcbaaf9e413e321ddVikram Aggarwal mUpdater.markConversationsRead(targets, read, false); 31804dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal updateSelection(); 319febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira } 320febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira 3210e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal /** 3220e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * Marks the important state of currently selected conversations (<b>and</b> the backing 3230e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * storage) to the value provided here. 3240e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * @param important is true if the conversations are to be marked as important, false if they 3250e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * are to be marked not important. 3260e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal */ 3277f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira private void markConversationsImportant(boolean important) { 328ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final Collection<Conversation> target = mCheckedSet.values(); 32904dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal final int priority = important ? UIProvider.ConversationPriority.HIGH 3307f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira : UIProvider.ConversationPriority.LOW; 3310e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal mUpdater.updateConversation(target, ConversationColumns.PRIORITY, priority); 3320e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal // Update the conversations in the selection too. 3330e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal for (final Conversation c : target) { 3340e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal c.priority = priority; 3350e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal } 33604dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal updateSelection(); 3377f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira } 3387f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira 33904dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal /** 3400e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal * Marks the selected conversations with the star setting provided here. 34104dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal * @param star true if you want all the conversations to have stars, false if you want to remove 34204dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal * stars from all conversations 34304dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal */ 344febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira private void starConversations(boolean star) { 345ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final Collection<Conversation> target = mCheckedSet.values(); 3460e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal mUpdater.updateConversation(target, ConversationColumns.STARRED, star); 3470e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal // Update the conversations in the selection too. 3480e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal for (final Conversation c : target) { 3490e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal c.starred = star; 3500e091c52d3a0135afb6904f78e06554567bfe591Vikram Aggarwal } 35104dc819886abc2e4f56e644b03449e29cdbae2d0Vikram Aggarwal updateSelection(); 352febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira } 353febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira 35411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 35511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public boolean onCreateActionMode(ActionMode mode, Menu menu) { 356ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedSet.addObserver(this); 3577f602f7a64f176894ccb7942a6642f22584c3894Vikram Aggarwal final MenuInflater inflater = mActivity.getMenuInflater(); 35811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira inflater.inflate(R.menu.conversation_list_selection_actions_menu, menu); 35911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira mActionMode = mode; 360db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein updateCount(); 36111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira return true; 36211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 36311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 36411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 36511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 366e5e917c10cbc4afd31358c0425954e2c27e0fb8eVikram Aggarwal // Update the actionbar to select operations available on the current conversation. 367ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final Collection<Conversation> conversations = mCheckedSet.values(); 368febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira boolean showStar = false; 369febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira boolean showMarkUnread = false; 3707f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira boolean showMarkImportant = false; 37177eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook boolean showMarkNotSpam = false; 37276b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook boolean showMarkAsPhishing = false; 3737f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira 3741e5bccefa627306120fbfd783838e1ef8b7fe0d8Jin Cao // TODO(shahrk): Clean up these dirty calls using Utils.setMenuItemPresent(...) or 37569419bb35240747d14765d4c74d4c2de58f4f8c5Rohan Shah // in another way 37669419bb35240747d14765d4c74d4c2de58f4f8c5Rohan Shah 377febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira for (Conversation conversation : conversations) { 378febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira if (!conversation.starred) { 379febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira showStar = true; 380febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira } 381febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira if (conversation.read) { 382febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira showMarkUnread = true; 383febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira } 3847f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira if (!conversation.isImportant()) { 3857f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira showMarkImportant = true; 3867f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira } 38777eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook if (conversation.spam) { 38877eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook showMarkNotSpam = true; 38977eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook } 39076b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook if (!conversation.phishing) { 39176b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook showMarkAsPhishing = true; 39276b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook } 39376b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook if (showStar && showMarkUnread && showMarkImportant && showMarkNotSpam && 39476b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook showMarkAsPhishing) { 395febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira break; 396febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira } 397febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira } 398ec86c424934205dcbc21078543be116d50e1b183Tony Mantler final boolean canStar = mFolder != null && !mFolder.isTrash(); 399334e64af904085984cdcbecbcbc18cf488a9ceaePaul Westbrook final MenuItem star = menu.findItem(R.id.star); 400ec86c424934205dcbc21078543be116d50e1b183Tony Mantler star.setVisible(showStar && canStar); 401334e64af904085984cdcbecbcbc18cf488a9ceaePaul Westbrook final MenuItem unstar = menu.findItem(R.id.remove_star); 402ec86c424934205dcbc21078543be116d50e1b183Tony Mantler unstar.setVisible(!showStar && canStar); 403334e64af904085984cdcbecbcbc18cf488a9ceaePaul Westbrook final MenuItem read = menu.findItem(R.id.read); 404febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira read.setVisible(!showMarkUnread); 405334e64af904085984cdcbecbcbc18cf488a9ceaePaul Westbrook final MenuItem unread = menu.findItem(R.id.unread); 406febeb5fd53b0041e3d3b74ff6e3ba414475b2b31Mindy Pereira unread.setVisible(showMarkUnread); 407a6b45218b8d90d7fc3a5ca0901293c71df404553Jin Cao 4089ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira // We only ever show one of: 4099ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira // 1) remove folder 4109ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira // 2) archive 41101f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira final MenuItem removeFolder = menu.findItem(R.id.remove_folder); 412aab9bc71f2d8742128361dff72f77543f81dde52Rohan Shah final MenuItem moveTo = menu.findItem(R.id.move_to); 413dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedy final MenuItem moveToInbox = menu.findItem(R.id.move_to_inbox); 4148c1058ee75ec4a5824a68c3c5275bc48d56bbad8Scott Kennedy final boolean showRemoveFolder = mFolder != null && mFolder.isType(FolderType.DEFAULT) 4159ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira && mFolder.supportsCapability(FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES) 41653b34250c0029ac3dae4c72822f79d9fad85caa4Tony Mantler && !mFolder.isProviderFolder() 41753b34250c0029ac3dae4c72822f79d9fad85caa4Tony Mantler && mAccount.supportsCapability(AccountCapabilities.ARCHIVE); 418aab9bc71f2d8742128361dff72f77543f81dde52Rohan Shah final boolean showMoveTo = mFolder != null 419aab9bc71f2d8742128361dff72f77543f81dde52Rohan Shah && mFolder.supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION); 420dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedy final boolean showMoveToInbox = mFolder != null 421dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedy && mFolder.supportsCapability(FolderCapabilities.ALLOWS_MOVE_TO_INBOX); 4229ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira removeFolder.setVisible(showRemoveFolder); 42328f3d5c247927890a45880345b4bf6788f29a820Scott Kennedy moveTo.setVisible(showMoveTo); 424dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedy moveToInbox.setVisible(showMoveToInbox); 425dd2ec688cf18e0ec132d936168ccaa3c43cdefb1Scott Kennedy 42669419bb35240747d14765d4c74d4c2de58f4f8c5Rohan Shah final MenuItem changeFolders = menu.findItem(R.id.change_folders); 42769419bb35240747d14765d4c74d4c2de58f4f8c5Rohan Shah changeFolders.setVisible(mAccount.supportsCapability( 42869419bb35240747d14765d4c74d4c2de58f4f8c5Rohan Shah UIProvider.AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV)); 42969419bb35240747d14765d4c74d4c2de58f4f8c5Rohan Shah 4309ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira if (mFolder != null && showRemoveFolder) { 43101f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira removeFolder.setTitle(mActivity.getActivityContext().getString(R.string.remove_folder, 43201f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira mFolder.name)); 43301f30509c4c8ad0d13b7635447b7f023c7a0cab7Mindy Pereira } 4349ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira final MenuItem archive = menu.findItem(R.id.archive); 4353047a9f03d9febaf2aba1e5ea0827e0b740d1ab2Andrew Sapperstein if (archive != null) { 4363047a9f03d9febaf2aba1e5ea0827e0b740d1ab2Andrew Sapperstein archive.setVisible( 4373047a9f03d9febaf2aba1e5ea0827e0b740d1ab2Andrew Sapperstein mAccount.supportsCapability(UIProvider.AccountCapabilities.ARCHIVE) && 4383047a9f03d9febaf2aba1e5ea0827e0b740d1ab2Andrew Sapperstein mFolder.supportsCapability(FolderCapabilities.ARCHIVE)); 43950cfeda191d0744d61d278890763c8d261389e03Mindy Pereira } 440334e64af904085984cdcbecbcbc18cf488a9ceaePaul Westbrook final MenuItem spam = menu.findItem(R.id.report_spam); 4419ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira spam.setVisible(!showMarkNotSpam 4429ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira && mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM) 4439ba4251297f1645af2490fcc2dc43f5063e12a29Mindy Pereira && mFolder.supportsCapability(FolderCapabilities.REPORT_SPAM)); 44477eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook final MenuItem notSpam = menu.findItem(R.id.mark_not_spam); 44577eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook notSpam.setVisible(showMarkNotSpam && 44677eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM) && 44777eee625cd8c317c605acfd06cd3a7e22120a0fdPaul Westbrook mFolder.supportsCapability(FolderCapabilities.MARK_NOT_SPAM)); 44876b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook final MenuItem phishing = menu.findItem(R.id.report_phishing); 44976b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook phishing.setVisible(showMarkAsPhishing && 45076b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_PHISHING) && 45176b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook mFolder.supportsCapability(FolderCapabilities.REPORT_PHISHING)); 45276b2062b8c6d18a7b3a05292c385b47b0fcbd09fPaul Westbrook 453334e64af904085984cdcbecbcbc18cf488a9ceaePaul Westbrook final MenuItem mute = menu.findItem(R.id.mute); 45450cfeda191d0744d61d278890763c8d261389e03Mindy Pereira if (mute != null) { 45550cfeda191d0744d61d278890763c8d261389e03Mindy Pereira mute.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.MUTE) 456962a6922af499db189ace88ed3ba518946764197Scott Kennedy && (mFolder != null && mFolder.isInbox())); 45750cfeda191d0744d61d278890763c8d261389e03Mindy Pereira } 4587f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira final MenuItem markImportant = menu.findItem(R.id.mark_important); 4597f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira markImportant.setVisible(showMarkImportant 4607f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira && mAccount.supportsCapability(UIProvider.AccountCapabilities.MARK_IMPORTANT)); 4617f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira final MenuItem markNotImportant = menu.findItem(R.id.mark_not_important); 4627f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira markNotImportant.setVisible(!showMarkImportant 4637f0a962513503cb01aec093b14c1b48dfae08f12Mindy Pereira && mAccount.supportsCapability(UIProvider.AccountCapabilities.MARK_IMPORTANT)); 464512821c11d89d49908f3cfdee0b582601f500f3dJin Cao 465512821c11d89d49908f3cfdee0b582601f500f3dJin Cao boolean shouldShowDiscardOutbox = mFolder != null && mFolder.isType(FolderType.OUTBOX); 466512821c11d89d49908f3cfdee0b582601f500f3dJin Cao mDiscardOutboxMenuItem = menu.findItem(R.id.discard_outbox); 467512821c11d89d49908f3cfdee0b582601f500f3dJin Cao if (mDiscardOutboxMenuItem != null) { 468512821c11d89d49908f3cfdee0b582601f500f3dJin Cao mDiscardOutboxMenuItem.setVisible(shouldShowDiscardOutbox); 469512821c11d89d49908f3cfdee0b582601f500f3dJin Cao } 470512821c11d89d49908f3cfdee0b582601f500f3dJin Cao final boolean showDelete = mFolder != null && !mFolder.isType(FolderType.OUTBOX) 471ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook && mFolder.supportsCapability(UIProvider.FolderCapabilities.DELETE); 472b807337282fb19d1a38cdbe092a2f472b0e30321Mindy Pereira final MenuItem trash = menu.findItem(R.id.delete); 473ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook trash.setVisible(showDelete); 474ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook // We only want to show the discard drafts menu item if we are not showing the delete menu 475ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook // item, and the current folder is a draft folder and the account supports discarding 476ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook // drafts for a conversation 477ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook final boolean showDiscardDrafts = !showDelete && mFolder != null && mFolder.isDraft() && 478ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook mAccount.supportsCapability(AccountCapabilities.DISCARD_CONVERSATION_DRAFTS); 479ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook final MenuItem discardDrafts = menu.findItem(R.id.discard_drafts); 480ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook if (discardDrafts != null) { 481ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook discardDrafts.setVisible(showDiscardDrafts); 482ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook } 483ef3625472596326b910a4445307d1a8eb8c9cc3fPaul Westbrook 48411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira return true; 48511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 48611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 48711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 48811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public void onDestroyActionMode(ActionMode mode) { 48911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira mActionMode = null; 49011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // The action mode may have been destroyed due to this menu being deactivated, in which 49111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // case resources need not be cleaned up. However, if it was destroyed while this menu is 49211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // active, that implies the user hit "Done" in the top right, and resources need cleaning. 49311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira if (mActivated) { 49411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira destroy(); 49554f120f6ada40c7191811dfff99b151e9e192c78mindyp // Only commit destructive actions if the user actually pressed 49654f120f6ada40c7191811dfff99b151e9e192c78mindyp // done; otherwise, this was handled when we toggled conversation 49754f120f6ada40c7191811dfff99b151e9e192c78mindyp // selection state. 498ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy mActivity.getListHandler().commitDestructiveActions(true); 49911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 50011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 50111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 50211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 503ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao public void onSetPopulated(ConversationCheckedSet set) { 50411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // Noop. This object can only exist while the set is non-empty. 50511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 50611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 50711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 5081ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwal public void onSetEmpty() { 509ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal LogUtils.d(LOG_TAG, "onSetEmpty called."); 51011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira destroy(); 51111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 51211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 51311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @Override 514ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao public void onSetChanged(ConversationCheckedSet set) { 51511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // If the set is empty, the menu buttons are invalid and most like the menu will be cleaned 51611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // up. Avoid making any changes to stop flickering ("Add Star" -> "Remove Star") just 51711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira // before hiding the menu. 51811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira if (set.isEmpty()) { 51911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira return; 52011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 521db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein updateCount(); 52211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 52311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 52411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira /** 525db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein * Updates the visible count of how many conversations are selected. 526db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein */ 527db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein private void updateCount() { 528db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein if (mActionMode != null) { 529e64d20ca9e541ef9f48b31bd5ae92fa02b64327aAndrew Sapperstein mActionMode.setTitle(String.format("%d", mCheckedSet.size())); 530db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein } 531db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein } 532db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein 533db861e9f08677da6d685d9cffc9072d2f98c0944Andrew Sapperstein /** 534e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal * Activates and shows this menu (essentially starting an {@link ActionMode}) if the selected 535e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal * set is non-empty. 53611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira */ 53711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public void activate() { 538ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedSet.isEmpty()) { 539e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal return; 540e128fc21fab03f6d66c656efeee2155fab449a7fVikram Aggarwal } 5412f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein mListController.onCabModeEntered(); 54211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira mActivated = true; 54311b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira if (mActionMode == null) { 54452882ff08fe9420fe2dbb3f681545a330222e9c8Andrew Sapperstein mActivity.startSupportActionMode(this); 54511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 54611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 54711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 54811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira /** 54911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * De-activates and hides the menu (essentially disabling the {@link ActionMode}), but maintains 55011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * the selection conversation set, and internally updates state as necessary. 55111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira */ 55211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public void deactivate() { 553cc139833bc5829ba70244519e9870de783c41848Scott Kennedy mListController.onCabModeExited(); 5544c92874d9acedc81184339645b24eaeebacbb782Andrew Sapperstein mActivated = false; 55511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira if (mActionMode != null) { 55611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira mActionMode.finish(); 55711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 55811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 55911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 56011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira @VisibleForTesting 5614c92874d9acedc81184339645b24eaeebacbb782Andrew Sapperstein /** 5624c92874d9acedc81184339645b24eaeebacbb782Andrew Sapperstein * Returns true if CAB mode is active. 5634c92874d9acedc81184339645b24eaeebacbb782Andrew Sapperstein */ 56411b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira public boolean isActivated() { 56511b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira return mActivated; 56611b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 56711b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira 56811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira /** 56911b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira * Destroys and cleans up the resources associated with this menu. 57011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira */ 571ad6d6282136b54090f1bf80ff5d37056ff5907c8Vikram Aggarwal private void destroy() { 57211b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira deactivate(); 573ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedSet.removeObserver(this); 574ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao clearChecked(); 5754f4782bcc53e13b30f1fd417beb1a6c04a54faedVikram Aggarwal mUpdater.refreshConversationList(); 57614f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira if (mAccountObserver != null) { 57714f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira mAccountObserver.unregisterAndDestroy(); 57814f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira mAccountObserver = null; 57914f64ec84173e5ee8b7157a74e8d62eff7693c19Mindy Pereira } 58011b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira } 58111b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira} 582