Merge "Use a single view for the accountswitchspinner." into jb-ub-mail
diff --git a/res/menu/conversation_actions.xml b/res/menu/conversation_actions.xml
index 60599f6..99cd4ec 100644
--- a/res/menu/conversation_actions.xml
+++ b/res/menu/conversation_actions.xml
@@ -68,6 +68,12 @@
android:id="@+id/report_spam"
android:title="@string/report_spam"
android:icon="@drawable/ic_spam_normal_holo_light" />
+ <!-- Depends on AccountCapabilities.REPORT_SPAM -->
+ <item
+ android:id="@+id/mark_not_spam"
+ android:title="@string/mark_not_spam"
+ android:icon="@drawable/ic_spam_normal_holo_light"
+ android:visible="false" />
<!-- Always available -->
<item android:id="@+id/settings"
diff --git a/res/menu/conversation_list_selection_actions_menu.xml b/res/menu/conversation_list_selection_actions_menu.xml
index a0d9b2a..1c1d60d 100644
--- a/res/menu/conversation_list_selection_actions_menu.xml
+++ b/res/menu/conversation_list_selection_actions_menu.xml
@@ -86,5 +86,11 @@
android:title="@string/report_spam"
android:showAsAction="never"
android:icon="@drawable/ic_spam_normal_holo_light" />
+ <!-- Availability based on account -->
+ <item
+ android:id="@+id/mark_not_spam"
+ android:title="@string/mark_not_spam"
+ android:showAsAction="never"
+ android:icon="@drawable/ic_spam_normal_holo_light" />
</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d9c5014..dbf709e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -113,8 +113,10 @@
<string name="remove_star">Remove star</string>
<!-- Menu item: archive this conversation -->
<string name="archive">Archive</string>
- <!-- Menu item: report this conversation as spam -->
+ <!-- Menu item: report this conversation as spam [CHAR LIMIT = 30] -->
<string name="report_spam">Report spam</string>
+ <!-- Menu item: report this conversation not as spam [CHAR LIMIT = 30] -->
+ <string name="mark_not_spam">Not spam</string>
<!-- Menu item: delete this conversation -->
<string name="delete">Delete</string>
<!-- Menu item: next conversation -->
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index 23a2cda..4bd3594 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -1184,6 +1184,7 @@
public static final int ARCHIVE = 3;
public static final int MUTE = 4;
public static final int REPORT_SPAM = 5;
+ public static final int REPORT_NOT_SPAM = 6;
public static final int MOSTLY_ARCHIVE = MOSTLY | ARCHIVE;
public static final int MOSTLY_DELETE = MOSTLY | DELETE;
@@ -1294,12 +1295,16 @@
.build();
break;
case REPORT_SPAM:
+ case REPORT_NOT_SPAM:
sProvider.deleteLocal(mUri, ConversationCursor.this);
+ final String operation = mType == REPORT_SPAM ?
+ ConversationOperations.REPORT_SPAM :
+ ConversationOperations.REPORT_NOT_SPAM;
+
// Create an update operation that represents report spam
op = ContentProviderOperation.newUpdate(uri).withValue(
- ConversationOperations.OPERATION_KEY,
- ConversationOperations.REPORT_SPAM).build();
+ ConversationOperations.OPERATION_KEY, operation).build();
break;
default:
throw new UnsupportedOperationException(
@@ -1638,6 +1643,13 @@
}
/**
+ * As above, for report not spam
+ */
+ public int reportNotSpam(Context context, Collection<Conversation> conversations) {
+ return applyAction(context, conversations, ConversationOperation.REPORT_NOT_SPAM);
+ }
+
+ /**
* As above, for mostly archive
*/
public int mostlyArchive(Context context, Collection<Conversation> conversations) {
diff --git a/src/com/android/mail/browse/SelectedConversationsActionMenu.java b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
index 07bed28..ab93bf6 100644
--- a/src/com/android/mail/browse/SelectedConversationsActionMenu.java
+++ b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
@@ -119,6 +119,12 @@
case R.id.report_spam:
mUpdater.delete(mSelectionSet.values(), mUpdater.getBatchAction(R.id.report_spam));
break;
+ case R.id.mark_not_spam:
+ // Currently, since spam messages are only shown in list with other spam messages,
+ // marking a message not as spam is a destructive action
+ mUpdater.delete(mSelectionSet.values(),
+ mUpdater.getBatchAction(R.id.mark_not_spam));
+ break;
case R.id.read:
markConversationsRead(true);
break;
@@ -305,6 +311,7 @@
boolean showStar = false;
boolean showMarkUnread = false;
boolean showMarkImportant = false;
+ boolean showMarkNotSpam = false;
for (Conversation conversation : conversations) {
if (!conversation.starred) {
@@ -316,7 +323,10 @@
if (!conversation.isImportant()) {
showMarkImportant = true;
}
- if (showStar && showMarkUnread && showMarkImportant) {
+ if (conversation.spam) {
+ showMarkNotSpam = true;
+ }
+ if (showStar && showMarkUnread && showMarkImportant && showMarkNotSpam) {
break;
}
}
@@ -333,7 +343,11 @@
mFolder.supportsCapability(FolderCapabilities.ARCHIVE));
final MenuItem spam = menu.findItem(R.id.report_spam);
spam.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM) &&
- mFolder.supportsCapability(FolderCapabilities.ARCHIVE));
+ mFolder.supportsCapability(FolderCapabilities.REPORT_SPAM));
+ final MenuItem notSpam = menu.findItem(R.id.mark_not_spam);
+ notSpam.setVisible(showMarkNotSpam &&
+ mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM) &&
+ mFolder.supportsCapability(FolderCapabilities.MARK_NOT_SPAM));
final MenuItem mute = menu.findItem(R.id.mute);
mute.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.MUTE));
final MenuItem markImportant = menu.findItem(R.id.mark_important);
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index f2b7c0b..9b61314 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -173,34 +173,38 @@
*/
public static final int REPORT_SPAM = 0x0002;
/**
+ * Whether the server allows reporting phishing back.
+ */
+ public static final int REPORT_PHISHING = 0x0004;
+ /**
* Whether the server supports a concept of Archive: removing mail from the Inbox but
* keeping it around.
*/
- public static final int ARCHIVE = 0x0004;
+ public static final int ARCHIVE = 0x0008;
/**
* Whether the server will stop notifying on updates to this thread? This requires
* THREADED_CONVERSATIONS to be true, otherwise it should be ignored.
*/
- public static final int MUTE = 0x0008;
+ public static final int MUTE = 0x0010;
/**
* Whether the server supports searching over all messages. This requires SYNCABLE_FOLDERS
* to be true, otherwise it should be ignored.
*/
- public static final int SERVER_SEARCH = 0x0010;
+ public static final int SERVER_SEARCH = 0x0020;
/**
* Whether the server supports constraining search to a single folder. Requires
* SYNCABLE_FOLDERS, otherwise it should be ignored.
*/
- public static final int FOLDER_SERVER_SEARCH = 0x0020;
+ public static final int FOLDER_SERVER_SEARCH = 0x0040;
/**
* Whether the server sends us sanitized HTML (guaranteed to not contain malicious HTML).
*/
- public static final int SANITIZED_HTML = 0x0040;
+ public static final int SANITIZED_HTML = 0x0080;
/**
* Whether the server allows synchronization of draft messages. This does NOT require
* SYNCABLE_FOLDERS to be set.
*/
- public static final int DRAFT_SYNCHRONIZATION = 0x0080;
+ public static final int DRAFT_SYNCHRONIZATION = 0x0100;
/**
* Does the server allow the user to compose mails (and reply) using addresses other than
* their account name? For instance, GMail allows users to set FROM addresses that are
@@ -208,54 +212,54 @@
* FROM: address like user@android.com. If the user has enabled multiple FROM address, he
* can compose (and reply) using either address.
*/
- public static final int MULTIPLE_FROM_ADDRESSES = 0x0100;
+ public static final int MULTIPLE_FROM_ADDRESSES = 0x0200;
/**
* Whether the server allows the original message to be included in the reply by setting a
* flag on the reply. If we can avoid including the entire previous message, we save on
* bandwidth (replies are shorter).
*/
- public static final int SMART_REPLY = 0x0200;
+ public static final int SMART_REPLY = 0x0400;
/**
* Does this account support searching locally, on the device? This requires the backend
* storage to support a mechanism for searching.
*/
- public static final int LOCAL_SEARCH = 0x0400;
+ public static final int LOCAL_SEARCH = 0x0800;
/**
* Whether the server supports a notion of threaded conversations: where replies to messages
* are tagged to keep conversations grouped. This could be full threading (each message
* lists its parent) or conversation-level threading (each message lists one conversation
* which it belongs to)
*/
- public static final int THREADED_CONVERSATIONS = 0x0800;
+ public static final int THREADED_CONVERSATIONS = 0x1000;
/**
* Whether the server supports allowing a conversation to be in multiple folders. (Or allows
* multiple folders on a single conversation)
*/
- public static final int MULTIPLE_FOLDERS_PER_CONV = 0x1000;
+ public static final int MULTIPLE_FOLDERS_PER_CONV = 0x2000;
/**
* Whether the provider supports undoing operations. If it doesn't, never show the undo bar.
*/
- public static final int UNDO = 0x2000;
+ public static final int UNDO = 0x4000;
/**
* Whether the account provides help content.
*/
- public static final int HELP_CONTENT = 0x4000;
+ public static final int HELP_CONTENT = 0x8000;
/**
* Whether the account provides a way to send feedback content.
*/
- public static final int SEND_FEEDBACK = 0x8000;
+ public static final int SEND_FEEDBACK = 0x10000;
/**
* Whether the account provides a mechanism for marking conversations as important.
*/
- public static final int MARK_IMPORTANT = 0x10000;
+ public static final int MARK_IMPORTANT = 0x20000;
/**
* Whether initial conversation queries should use a limit parameter
*/
- public static final int INITIAL_CONVERSATION_LIMIT = 0x20000;
+ public static final int INITIAL_CONVERSATION_LIMIT = 0x40000;
/**
* Whether the account cannot be used for sending
*/
- public static final int SENDING_UNAVAILABLE = 0x40000;
+ public static final int SENDING_UNAVAILABLE = 0x80000;
}
public static final class AccountColumns {
@@ -577,29 +581,35 @@
public static final int REPORT_SPAM = 0x0020;
/**
+ * For accounts that support report spam, this will indicate that this folder supports
+ * the mark not functionality.
+ */
+ public static final int MARK_NOT_SPAM = 0x0040;
+
+ /**
* For accounts that support mute, this will indicate if a mute is performed from within
* this folder, the action is destructive.
*/
- public static final int DESTRUCTIVE_MUTE = 0x0040;
+ public static final int DESTRUCTIVE_MUTE = 0x0080;
/**
* Indicates that a folder supports settings (sync lookback, etc.)
*/
- public static final int SUPPORTS_SETTINGS = 0x0080;
+ public static final int SUPPORTS_SETTINGS = 0x0100;
/**
* All the messages in this folder are important.
*/
- public static final int ONLY_IMPORTANT = 0x0100;
+ public static final int ONLY_IMPORTANT = 0x0200;
/**
* Deletions in this folder can't be undone (could include archive if desirable)
*/
- public static final int DELETE_ACTION_FINAL = 0x0200;
+ public static final int DELETE_ACTION_FINAL = 0x0400;
/**
* This folder is virtual, i.e. contains conversations potentially pulled from other
* folders, potentially even from different accounts. Examples might be a "starred"
* folder, or an "unread" folder (per account or provider-wide)
*/
- public static final int IS_VIRTUAL = 0x400;
+ public static final int IS_VIRTUAL = 0x0800;
}
public static final class FolderColumns {
@@ -938,6 +948,11 @@
*/
public static final String REPORT_SPAM = "report_spam";
+ /**
+ * Report not spam operation
+ */
+ public static final String REPORT_NOT_SPAM = "report_not_spam";
+
private ConversationOperations() {
}
}
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index fcb12f2..c80d945 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -77,6 +77,7 @@
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -649,6 +650,11 @@
case R.id.report_spam:
delete(target, getAction(R.id.report_spam, target));
break;
+ case R.id.mark_not_spam:
+ // Currently, since spam messages are only shown in list with other spam messages,
+ // marking a message not as spam is a destructive action
+ delete(target, getAction(R.id.mark_not_spam, target));
+ break;
case R.id.inside_conversation_unread:
// TODO(viki): This is strange, and potentially incorrect. READ is an int column
// in the provider.
@@ -1483,7 +1489,7 @@
*/
private final int mAction;
/** The action will act upon these conversations */
- private final Collection<Conversation> mTarget = new ArrayList<Conversation>();
+ private final Collection<Conversation> mTarget;
/** Whether this destructive action has already been performed */
private boolean mCompleted;
/** Whether this is an action on the currently selected set. */
@@ -1498,7 +1504,7 @@
*/
public ConversationAction(int action, Collection<Conversation> target, boolean isBatch) {
mAction = action;
- mTarget.addAll(target);
+ mTarget = ImmutableList.copyOf(target);
mIsSelectedSet = isBatch;
}
@@ -1553,6 +1559,10 @@
LogUtils.d(LOG_TAG, "Reporting spam");
mConversationListCursor.reportSpam(mContext, mTarget);
break;
+ case R.id.mark_not_spam:
+ LogUtils.d(LOG_TAG, "Marking not spam");
+ mConversationListCursor.reportNotSpam(mContext, mTarget);
+ break;
case R.id.remove_star:
LogUtils.d(LOG_TAG, "Removing star");
// Star removal is destructive in the Starred folder.
@@ -1980,7 +1990,7 @@
* to be animated away from the current folder.
*/
private class FolderDestruction implements DestructiveAction {
- private final Collection<Conversation> mTarget = new ArrayList<Conversation>();
+ private final Collection<Conversation> mTarget;
private final ArrayList<Folder> mFolderList = new ArrayList<Folder>();
private final boolean mIsDestructive;
/** Whether this destructive action has already been performed */
@@ -1993,7 +2003,7 @@
*/
private FolderDestruction(final Collection<Conversation> target,
final Collection<Folder> folders, boolean isDestructive, boolean isBatch) {
- mTarget.addAll(target);
+ mTarget = ImmutableList.copyOf(target);
mFolderList.addAll(folders);
mIsDestructive = isDestructive;
mIsSelectedSet = isBatch;
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index faea9e0..6a37e14 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -312,6 +312,10 @@
mAccount.supportsCapability(AccountCapabilities.REPORT_SPAM) && mFolder != null
&& mFolder.supportsCapability(FolderCapabilities.REPORT_SPAM)
&& !mConversation.spam);
+ Utils.setMenuItemVisibility(menu, R.id.mark_not_spam,
+ mAccount.supportsCapability(AccountCapabilities.REPORT_SPAM) && mFolder != null
+ && mFolder.supportsCapability(FolderCapabilities.MARK_NOT_SPAM)
+ && mConversation.spam);
Utils.setMenuItemVisibility(
menu,
R.id.mute,