blob: 0db79d0959a89dbe94280abfab03778884cd4fc1 [file] [log] [blame]
Mindy Pereira11b0bbd2012-01-24 10:06:17 -08001/*
2 * Copyright (C) 2010 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.browse;
19
20import com.android.mail.R;
Mindy Pereira30d2d322012-02-03 08:40:49 -080021import com.android.mail.providers.Account;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080022import com.android.mail.providers.Conversation;
Mindy Pereira4f166de2012-02-14 13:40:58 -080023import com.android.mail.providers.Folder;
Mindy Pereiraefe3d252012-03-01 14:20:44 -080024import com.android.mail.providers.Settings;
Mindy Pereiraf98b3182012-02-22 11:07:13 -080025import com.android.mail.providers.UIProvider;
Paul Westbrook334e64a2012-02-23 13:26:35 -080026import com.android.mail.providers.UIProvider.FolderCapabilities;
Marc Blank8d69d4e2012-01-25 12:04:28 -080027import com.android.mail.providers.UIProvider.ConversationColumns;
Mindy Pereirafac92d72012-02-01 10:58:33 -080028import com.android.mail.ui.AnimatedAdapter;
Mindy Pereira9879d4c2012-01-31 09:34:18 -080029import com.android.mail.ui.ActionCompleteListener;
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080030import com.android.mail.ui.ConversationSelectionSet;
31import com.android.mail.ui.ConversationSetObserver;
Mindy Pereiraf3dfb152012-02-06 12:55:13 -080032import com.android.mail.ui.FoldersSelectionDialog;
Vikram Aggarwald247dc92012-02-10 15:49:01 -080033import com.android.mail.ui.RestrictedActivity;
Mindy Pereirac9d59182012-03-22 16:06:46 -070034import com.android.mail.ui.FoldersSelectionDialog.FolderChangeCommitListener;
Mindy Pereira7ad3b872012-02-22 09:10:46 -080035import com.android.mail.ui.UndoBarView.UndoListener;
36import com.android.mail.ui.UndoOperation;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080037import com.android.mail.utils.LogUtils;
Mindy Pereiraefe3d252012-03-01 14:20:44 -080038import com.android.mail.utils.Utils;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080039import com.google.common.annotations.VisibleForTesting;
40
Mindy Pereirad92e9f32012-02-03 09:10:58 -080041import java.util.ArrayList;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080042import java.util.Collection;
Mindy Pereira0825efd2012-02-15 17:30:32 -080043import java.util.HashSet;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080044
Mindy Pereiraefe3d252012-03-01 14:20:44 -080045import android.app.AlertDialog;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080046import android.content.Context;
Mindy Pereiraefe3d252012-03-01 14:20:44 -080047import android.content.DialogInterface;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080048import android.view.ActionMode;
49import android.view.Menu;
50import android.view.MenuInflater;
51import android.view.MenuItem;
52
53/**
54 * A component that displays a custom view for an {@code ActionBar}'s {@code
55 * ContextMode} specific to operating on a set of conversations.
56 */
57public class SelectedConversationsActionMenu implements ActionMode.Callback,
Mindy Pereirac9d59182012-03-22 16:06:46 -070058 ConversationSetObserver, FolderChangeCommitListener {
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080059
60 private static final String LOG_TAG = new LogUtils().getLogTag();
61
62 /**
63 * The set of conversations to display the menu for.
64 */
65 protected final ConversationSelectionSet mSelectionSet;
Marc Blankce538182012-02-03 13:04:27 -080066 /**
67 * The set of conversations to marked for deletion
68 */
69 protected Collection<Conversation> mDeletionSet;
70 /**
71 * The new folder list (after selection)
72 */
Mindy Pereira6778f462012-03-23 18:01:55 -070073 protected ArrayList<Folder> mFolderChangeList;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080074
Vikram Aggarwald247dc92012-02-10 15:49:01 -080075 private final RestrictedActivity mActivity;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080076
Vikram Aggarwalcd8bf0a2012-02-14 13:13:18 -080077 /**
78 * Context of the activity. A dialog requires the context of an activity rather than the global
79 * root context of the process. So mContext = mActivity.getApplicationContext() will fail.
80 */
Mindy Pereira11b0bbd2012-01-24 10:06:17 -080081 private final Context mContext;
82
83 @VisibleForTesting
84 ActionMode mActionMode;
85
86 private boolean mActivated = false;
87
88 private Menu mMenu;
89
Mindy Pereirafac92d72012-02-01 10:58:33 -080090 private AnimatedAdapter mListAdapter;
Mindy Pereira9879d4c2012-01-31 09:34:18 -080091
Mindy Pereira96b5c352012-02-01 11:33:40 -080092 private ActionCompleteListener mActionCompleteListener;
93
Mindy Pereira7ad3b872012-02-22 09:10:46 -080094 private UndoListener mUndoListener;
95
Mindy Pereira30d2d322012-02-03 08:40:49 -080096 private Account mAccount;
97
Mindy Pereirad92e9f32012-02-03 09:10:58 -080098 protected int mCheckedItem = 0;
99
Mindy Pereira4f166de2012-02-14 13:40:58 -0800100 private Folder mFolder;
101
Vikram Aggarwale128fc22012-04-04 12:33:34 -0700102 private final ActionCompleteListener mDeleteListener =
103 new DestructiveActionListener(R.id.delete);
104 private final ActionCompleteListener mArchiveListener =
105 new DestructiveActionListener(R.id.archive);
106 private final ActionCompleteListener mMuteListener = new DestructiveActionListener(R.id.mute);
107 private final ActionCompleteListener mSpamListener =
108 new DestructiveActionListener(R.id.report_spam);
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800109
Vikram Aggarwald247dc92012-02-10 15:49:01 -0800110 public SelectedConversationsActionMenu(RestrictedActivity activity,
Mindy Pereira96b5c352012-02-01 11:33:40 -0800111 ConversationSelectionSet selectionSet, AnimatedAdapter adapter,
Mindy Pereira7ad3b872012-02-22 09:10:46 -0800112 ActionCompleteListener listener, UndoListener undoListener, Account account,
113 Folder folder) {
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800114 mSelectionSet = selectionSet;
115 mActivity = activity;
Vikram Aggarwalcd8bf0a2012-02-14 13:13:18 -0800116 mContext = mActivity.getActivityContext();
Mindy Pereirafac92d72012-02-01 10:58:33 -0800117 mListAdapter = adapter;
Mindy Pereira96b5c352012-02-01 11:33:40 -0800118 mActionCompleteListener = listener;
Mindy Pereira7ad3b872012-02-22 09:10:46 -0800119 mUndoListener = undoListener;
Mindy Pereira30d2d322012-02-03 08:40:49 -0800120 mAccount = account;
Mindy Pereira4f166de2012-02-14 13:40:58 -0800121 mFolder = folder;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800122 }
123
124 @Override
125 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
126 boolean handled = true;
Marc Blank8d69d4e2012-01-25 12:04:28 -0800127 Collection<Conversation> conversations = mSelectionSet.values();
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800128 switch (item.getItemId()) {
129 case R.id.delete:
Mindy Pereiraefe3d252012-03-01 14:20:44 -0800130 performDestructiveAction(R.id.delete, mDeleteListener);
Marc Blank8d69d4e2012-01-25 12:04:28 -0800131 break;
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800132 case R.id.archive:
Mindy Pereiraefe3d252012-03-01 14:20:44 -0800133 performDestructiveAction(R.id.archive, mArchiveListener);
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800134 break;
Mindy Pereira830c00f2012-02-22 11:43:49 -0800135 case R.id.mute:
136 mListAdapter.delete(conversations, mMuteListener);
137 break;
138 case R.id.report_spam:
139 mListAdapter.delete(conversations, mSpamListener);
140 break;
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800141 case R.id.read:
142 markConversationsRead(true);
143 break;
144 case R.id.unread:
145 markConversationsRead(false);
Marc Blank8d69d4e2012-01-25 12:04:28 -0800146 break;
147 case R.id.star:
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800148 starConversations(true);
149 break;
150 case R.id.remove_star:
151 starConversations(false);
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800152 break;
Mindy Pereira30d2d322012-02-03 08:40:49 -0800153 case R.id.change_folder:
154 showChangeFoldersDialog();
155 break;
Mindy Pereira7f0a9622012-02-29 15:00:34 -0800156 case R.id.mark_important:
157 markConversationsImportant(true);
158 break;
159 case R.id.mark_not_important:
160 markConversationsImportant(false);
161 break;
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800162 default:
163 handled = false;
164 break;
165 }
166 return handled;
167 }
168
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700169 /**
170 * Clear the selection and perform related UI changes to keep the state consistent.
171 */
172 private void clearSelection() {
173 mSelectionSet.clear();
174 // Redraw with changes
175 mListAdapter.notifyDataSetChanged();
176 }
177
Mindy Pereiraefe3d252012-03-01 14:20:44 -0800178 private void performDestructiveAction(int id, final ActionCompleteListener listener) {
179 Settings settings = mActivity.getSettings();
180 final Collection<Conversation> conversations = mSelectionSet.values();
181 boolean showDialog = false;
182 if (settings != null) {
183 showDialog = (id == R.id.delete) ? settings.confirmDelete : settings.confirmArchive;
184 }
185 if (showDialog) {
186 int resId = id == R.id.delete ? R.plurals.confirm_delete_conversation
187 : R.plurals.confirm_archive_conversation;
188 CharSequence message = Utils.formatPlural(mContext, resId, conversations.size());
189 new AlertDialog.Builder(mContext).setMessage(message)
190 .setPositiveButton(R.string.ok, new AlertDialog.OnClickListener() {
191 @Override
192 public void onClick(DialogInterface dialog, int which) {
193 mListAdapter.delete(conversations, listener);
194 }
195
196 }).setNegativeButton(R.string.cancel, null).create().show();
197 } else {
198 mListAdapter.delete(conversations, listener);
199 }
200 }
201
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800202 private void markConversationsRead(boolean read) {
203 Collection<Conversation> conversations = mSelectionSet.values();
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800204 Conversation.updateBoolean(mContext, conversations, ConversationColumns.READ, read);
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700205 clearSelection();
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800206 }
207
Mindy Pereira7f0a9622012-02-29 15:00:34 -0800208 private void markConversationsImportant(boolean important) {
209 Collection<Conversation> conversations = mSelectionSet.values();
210 int priority = important ? UIProvider.ConversationPriority.HIGH
211 : UIProvider.ConversationPriority.LOW;
212 Conversation.updateInt(mContext, conversations, ConversationColumns.PRIORITY, priority);
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700213 clearSelection();
Mindy Pereira7f0a9622012-02-29 15:00:34 -0800214 }
215
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800216 private void starConversations(boolean star) {
217 Collection<Conversation> conversations = mSelectionSet.values();
218 if (conversations.size() > 0) {
219 Conversation.updateBoolean(mContext, conversations,
220 ConversationColumns.STARRED, star);
221 }
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700222 clearSelection();
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800223 }
224
Mindy Pereira30d2d322012-02-03 08:40:49 -0800225 private void showChangeFoldersDialog() {
Vikram Aggarwald247dc92012-02-10 15:49:01 -0800226 new FoldersSelectionDialog(mContext, mAccount, this, mSelectionSet.values()).show();
Mindy Pereiraf3dfb152012-02-06 12:55:13 -0800227 }
Marc Blankce538182012-02-03 13:04:27 -0800228
Mindy Pereiraf3dfb152012-02-06 12:55:13 -0800229 @Override
Mindy Pereira6778f462012-03-23 18:01:55 -0700230 public void onFolderChangesCommit(ArrayList<Folder> folderChangeList) {
Mindy Pereiraf3dfb152012-02-06 12:55:13 -0800231 mFolderChangeList = folderChangeList;
Mindy Pereiraf3dfb152012-02-06 12:55:13 -0800232 // Do the change here...
Mindy Pereira4f166de2012-02-14 13:40:58 -0800233 // Get currently active folder info and compare it to the list
234 // these conversations have been given; if they no longer contain
235 // the selected folder, delete them from the list.
Mindy Pereira0825efd2012-02-15 17:30:32 -0800236 HashSet<String> folderUris = new HashSet<String>();
Mindy Pereira6778f462012-03-23 18:01:55 -0700237 if (folderChangeList != null && !folderChangeList.isEmpty()) {
238 for (Folder f : folderChangeList) {
239 folderUris.add(f.uri.toString());
240 }
Mindy Pereira0825efd2012-02-15 17:30:32 -0800241 }
Mindy Pereira6f9833a2012-03-21 13:53:12 -0700242 if (!folderUris.contains(mFolder.uri.toString())) {
Mindy Pereira4f166de2012-02-14 13:40:58 -0800243 final Collection<Conversation> conversations = mSelectionSet.values();
244 // Indicate delete on update (i.e. no longer in this folder)
245 mDeletionSet = new ArrayList<Conversation>();
246 for (Conversation conv : conversations) {
247 conv.localDeleteOnUpdate = true;
248 // For Gmail, add... if (noLongerInList(conv))...
249 mDeletionSet.add(conv);
250 }
251 // Delete the local delete items (all for now) and when done,
252 // update...
253 mListAdapter.delete(mDeletionSet, mFolderChangeListener);
254 } else {
255 mFolderChangeListener.onActionComplete();
Mindy Pereirad92e9f32012-02-03 09:10:58 -0800256 }
Mindy Pereira30d2d322012-02-03 08:40:49 -0800257 }
258
Vikram Aggarwale128fc22012-04-04 12:33:34 -0700259 private final ActionCompleteListener mFolderChangeListener = new ActionCompleteListener() {
Marc Blankce538182012-02-03 13:04:27 -0800260 @Override
261 public void onActionComplete() {
262 mActionCompleteListener.onActionComplete();
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800263 Collection<Conversation> deletionSet = mDeletionSet;
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800264 if (deletionSet != null && deletionSet.size() > 0) {
Vikram Aggarwal6fbc87a2012-03-15 15:24:00 -0700265 // Only show undo if this was a destructive folder change.
266 UndoOperation undoOp = new UndoOperation(deletionSet.size(), R.id.change_folder);
267 mUndoListener.onUndoAvailable(undoOp);
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800268 mDeletionSet = null;
269 }
Mindy Pereira6778f462012-03-23 18:01:55 -0700270 StringBuilder foldersUrisString = new StringBuilder();
271 boolean first = true;
272 for (Folder f : mFolderChangeList) {
273 if (first) {
274 first = false;
275 } else {
276 foldersUrisString.append(',');
277 }
278 foldersUrisString.append(f.uri.toString());
279 }
Vikram Aggarwald247dc92012-02-10 15:49:01 -0800280 Conversation.updateString(mContext, mSelectionSet.values(),
Mindy Pereira6778f462012-03-23 18:01:55 -0700281 ConversationColumns.FOLDER_LIST, foldersUrisString.toString());
282 Conversation.updateString(mContext, mSelectionSet.values(),
283 ConversationColumns.RAW_FOLDERS,
Mindy Pereira5b84f412012-03-25 12:45:14 -0700284 Folder.getSerializedFolderString(mFolder, mFolderChangeList));
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700285 clearSelection();
Mindy Pereiraf98b3182012-02-22 11:07:13 -0800286 }
287 };
Marc Blankce538182012-02-03 13:04:27 -0800288
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800289 @Override
290 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
291 mSelectionSet.addObserver(this);
292 MenuInflater inflater = mActivity.getMenuInflater();
293 inflater.inflate(R.menu.conversation_list_selection_actions_menu, menu);
294 mActionMode = mode;
295 mMenu = menu;
296 updateCount();
297 return true;
298 }
299
300 @Override
301 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800302 // Determine read/ unread
303 // Star/ unstar
304 Collection<Conversation> conversations = mSelectionSet.values();
305 boolean showStar = false;
306 boolean showMarkUnread = false;
Mindy Pereira7f0a9622012-02-29 15:00:34 -0800307 boolean showMarkImportant = false;
308
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800309 for (Conversation conversation : conversations) {
310 if (!conversation.starred) {
311 showStar = true;
312 }
313 if (conversation.read) {
314 showMarkUnread = true;
315 }
Mindy Pereira7f0a9622012-02-29 15:00:34 -0800316 if (!conversation.isImportant()) {
317 showMarkImportant = true;
318 }
319 if (showStar && showMarkUnread && showMarkImportant) {
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800320 break;
321 }
322 }
Paul Westbrook334e64a2012-02-23 13:26:35 -0800323 final MenuItem star = menu.findItem(R.id.star);
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800324 star.setVisible(showStar);
Paul Westbrook334e64a2012-02-23 13:26:35 -0800325 final MenuItem unstar = menu.findItem(R.id.remove_star);
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800326 unstar.setVisible(!showStar);
Paul Westbrook334e64a2012-02-23 13:26:35 -0800327 final MenuItem read = menu.findItem(R.id.read);
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800328 read.setVisible(!showMarkUnread);
Paul Westbrook334e64a2012-02-23 13:26:35 -0800329 final MenuItem unread = menu.findItem(R.id.unread);
Mindy Pereirafebeb5f2012-02-14 15:08:13 -0800330 unread.setVisible(showMarkUnread);
Paul Westbrook334e64a2012-02-23 13:26:35 -0800331 final MenuItem archive = menu.findItem(R.id.archive);
332 archive.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.ARCHIVE) &&
333 mFolder.supportsCapability(FolderCapabilities.ARCHIVE));
334 final MenuItem spam = menu.findItem(R.id.report_spam);
335 spam.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM) &&
336 mFolder.supportsCapability(FolderCapabilities.ARCHIVE));
337 final MenuItem mute = menu.findItem(R.id.mute);
Mindy Pereira830c00f2012-02-22 11:43:49 -0800338 mute.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.MUTE));
Mindy Pereira7f0a9622012-02-29 15:00:34 -0800339 final MenuItem markImportant = menu.findItem(R.id.mark_important);
340 markImportant.setVisible(showMarkImportant
341 && mAccount.supportsCapability(UIProvider.AccountCapabilities.MARK_IMPORTANT));
342 final MenuItem markNotImportant = menu.findItem(R.id.mark_not_important);
343 markNotImportant.setVisible(!showMarkImportant
344 && mAccount.supportsCapability(UIProvider.AccountCapabilities.MARK_IMPORTANT));
345
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800346 return true;
347 }
348
349 public void onPrepareActionMode() {
350 if (mActionMode != null) {
351 onPrepareActionMode(mActionMode, mActionMode.getMenu());
352 }
353 }
354
355 @Override
356 public void onDestroyActionMode(ActionMode mode) {
357 mActionMode = null;
358 // The action mode may have been destroyed due to this menu being deactivated, in which
359 // case resources need not be cleaned up. However, if it was destroyed while this menu is
360 // active, that implies the user hit "Done" in the top right, and resources need cleaning.
361 if (mActivated) {
362 destroy();
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800363 }
364 mMenu = null;
365 }
366
367 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800368 public void onSetPopulated(ConversationSelectionSet set) {
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800369 // Noop. This object can only exist while the set is non-empty.
370 }
371
372 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800373 public void onSetEmpty() {
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700374 LogUtils.d(LOG_TAG, "onSetEmpty called.");
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800375 destroy();
376 }
377
378 @Override
379 public void onSetChanged(ConversationSelectionSet set) {
380 // If the set is empty, the menu buttons are invalid and most like the menu will be cleaned
381 // up. Avoid making any changes to stop flickering ("Add Star" -> "Remove Star") just
382 // before hiding the menu.
383 if (set.isEmpty()) {
384 return;
385 }
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800386 updateCount();
387 }
388
389 /**
390 * Updates the visible count of how many conversations are selected.
391 */
392 private void updateCount() {
393 if (mActionMode != null) {
394 mActionMode.setTitle(mContext.getString(R.string.num_selected, mSelectionSet.size()));
395 }
396 }
397
398 /**
Vikram Aggarwale128fc22012-04-04 12:33:34 -0700399 * Activates and shows this menu (essentially starting an {@link ActionMode}) if the selected
400 * set is non-empty.
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800401 */
402 public void activate() {
Vikram Aggarwale128fc22012-04-04 12:33:34 -0700403 if (mSelectionSet.isEmpty()) {
404 // We have nothing to do since there is no conversation selected.
405 return;
406 }
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800407 mActivated = true;
408 if (mActionMode == null) {
409 mActivity.startActionMode(this);
410 }
411 }
412
413 /**
414 * De-activates and hides the menu (essentially disabling the {@link ActionMode}), but maintains
415 * the selection conversation set, and internally updates state as necessary.
416 */
417 public void deactivate() {
418 if (mActionMode != null) {
419 mActivated = false;
420 mActionMode.finish();
421 }
422 }
423
424 @VisibleForTesting
425 public boolean isActivated() {
426 return mActivated;
427 }
428
429 /**
430 * Destroys and cleans up the resources associated with this menu.
431 */
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700432 private void destroy() {
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800433 deactivate();
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800434 mSelectionSet.removeObserver(this);
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700435 clearSelection();
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800436 }
437
438 /**
439 * Disable the selected conversations menu item associated with a command
440 * id.
441 */
442 public void disableCommand(int id) {
443 enableMenuItem(id, false);
444 }
445
446 /**
447 * Enable the selected conversations menu item associated with a command
448 * id.
449 */
450 public void enableCommand(int id) {
451 enableMenuItem(id, true);
452 }
453
454 private void enableMenuItem(int id, boolean enable) {
455 if (mActivated) {
456 MenuItem item = mMenu.findItem(id);
457 if (item != null) {
458 item.setEnabled(enable);
459 }
460 }
461 }
Mindy Pereira830c00f2012-02-22 11:43:49 -0800462
Vikram Aggarwal54452ae2012-03-13 15:29:00 -0700463 private class DestructiveActionListener implements ActionCompleteListener {
464 private final int mAction;
Mindy Pereira830c00f2012-02-22 11:43:49 -0800465 public DestructiveActionListener(int action) {
466 mAction = action;
467 }
468
469 @Override
470 public void onActionComplete() {
471 // This is where we actually delete.
472 Collection<Conversation> conversations = mSelectionSet.values();
473 mActionCompleteListener.onActionComplete();
474 mUndoListener.onUndoAvailable(new UndoOperation(conversations.size(), mAction));
475 switch (mAction) {
476 case R.id.archive:
477 Conversation.archive(mContext, conversations);
478 break;
479 case R.id.delete:
480 Conversation.delete(mContext, conversations);
481 break;
482 case R.id.mute:
Paul Westbrook334e64a2012-02-23 13:26:35 -0800483 if (mFolder.supportsCapability(FolderCapabilities.DESTRUCTIVE_MUTE)) {
484 // Make sure to set the localDeleteOnUpdate flag for these conversatons.
485 for (Conversation conversation: conversations) {
486 conversation.localDeleteOnUpdate = true;
487 }
488 }
Mindy Pereira830c00f2012-02-22 11:43:49 -0800489 Conversation.mute(mContext, conversations);
490 break;
491 case R.id.report_spam:
492 Conversation.reportSpam(mContext, conversations);
493 break;
494 }
Vikram Aggarwalad6d6282012-03-28 09:16:14 -0700495 clearSelection();
Mindy Pereira830c00f2012-02-22 11:43:49 -0800496 }
Vikram Aggarwal54452ae2012-03-13 15:29:00 -0700497 }
Mindy Pereira11b0bbd2012-01-24 10:06:17 -0800498}