Only move selected convos if from same account
* Add accountUri column to Conversation
* Also add IS_VIRTUAL capability to Folder (for combined folders)
* Check that all conversations to be moved/relabeled from a virtual
folder are from the same account
Bug: 6280990
Change-Id: Idfc5b3017b16a9f8c1ae5063ba22c66f89d8ca4f
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 00223b5..484d6a2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -693,4 +693,9 @@
<!-- Camera format string for new image files. Passed to java.text.SimpleDateFormat. -->
<string name="image_file_name_format" translatable="false">"'IMG'_yyyyMMdd_HHmmss"</string>
+
+ <!-- The move message / change labels action can't be taken because the selected messages
+ come from different accounts -->
+ <string name="cant_move_or_change_labels">Can\'t move because selection contains multiple
+ accounts.</string>
</resources>
diff --git a/src/com/android/mail/browse/SelectedConversationsActionMenu.java b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
index b3a9488..13fd7cb 100644
--- a/src/com/android/mail/browse/SelectedConversationsActionMenu.java
+++ b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
@@ -20,24 +20,27 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.net.Uri;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.widget.Toast;
import com.android.mail.R;
import com.android.mail.providers.Account;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
+import com.android.mail.providers.MailAppProvider;
import com.android.mail.providers.Settings;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.ConversationColumns;
import com.android.mail.providers.UIProvider.FolderCapabilities;
import com.android.mail.ui.AbstractActivityController;
-import com.android.mail.ui.DestructiveAction;
import com.android.mail.ui.AnimatedAdapter;
import com.android.mail.ui.ConversationSelectionSet;
import com.android.mail.ui.ConversationSetObserver;
+import com.android.mail.ui.DestructiveAction;
import com.android.mail.ui.FoldersSelectionDialog;
import com.android.mail.ui.RestrictedActivity;
import com.android.mail.ui.SwipeableListView;
@@ -158,8 +161,31 @@
}
break;
case R.id.change_folder:
- new FoldersSelectionDialog(mContext, mAccount, mController, mSelectionSet.values(),
- true).show();
+ boolean cantMove = false;
+ Account acct = mAccount;
+ // Special handling for virtual folders
+ if (mFolder.supportsCapability(FolderCapabilities.IS_VIRTUAL)) {
+ Uri accountUri = null;
+ for (Conversation conv: mSelectionSet.values()) {
+ if (accountUri == null) {
+ accountUri = conv.accountUri;
+ } else if (!accountUri.equals(conv.accountUri)) {
+ // Tell the user why we can't do this
+ Toast.makeText(mContext, R.string.cant_move_or_change_labels,
+ Toast.LENGTH_LONG).show();
+ cantMove = true;
+ break;
+ }
+ }
+ if (!cantMove) {
+ // Get the actual account here, so that we display its folders in the dialog
+ acct = MailAppProvider.getAccountFromAccountUri(accountUri);
+ }
+ }
+ if (!cantMove) {
+ new FoldersSelectionDialog(mContext, acct, mController,
+ mSelectionSet.values(), true).show();
+ }
break;
case R.id.mark_important:
markConversationsImportant(true);
diff --git a/src/com/android/mail/providers/Conversation.java b/src/com/android/mail/providers/Conversation.java
index cba2ac7..1bb7d1c 100644
--- a/src/com/android/mail/providers/Conversation.java
+++ b/src/com/android/mail/providers/Conversation.java
@@ -16,14 +16,14 @@
package com.android.mail.providers;
-import com.google.common.collect.ImmutableList;
-
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import com.google.common.collect.ImmutableList;
+
import java.util.Collection;
import java.util.Collections;
@@ -51,6 +51,7 @@
public boolean spam;
public boolean muted;
public int color;
+ public Uri accountUri;
// Used within the UI to indicate the adapter position of this conversation
public transient int position;
@@ -96,6 +97,7 @@
dest.writeInt(spam ? 1 : 0);
dest.writeInt(muted ? 1 : 0);
dest.writeInt(color);
+ dest.writeParcelable(accountUri, 0);
}
private Conversation(Parcel in) {
@@ -120,6 +122,7 @@
spam = in.readInt() != 0;
muted = in.readInt() != 0;
color = in.readInt();
+ accountUri = in.readParcelable(null);
position = NO_POSITION;
localDeleteOnUpdate = false;
}
@@ -174,6 +177,8 @@
spam = cursor.getInt(UIProvider.CONVERSATION_IS_SPAM_COLUMN) != 0;
muted = cursor.getInt(UIProvider.CONVERSATION_MUTED_COLUMN) != 0;
color = cursor.getInt(UIProvider.CONVERSATION_COLOR_COLUMN);
+ String account = cursor.getString(UIProvider.CONVERSATION_ACCOUNT_URI_COLUMN);
+ accountUri = !TextUtils.isEmpty(account) ? Uri.parse(account) : null;
position = NO_POSITION;
localDeleteOnUpdate = false;
}
@@ -186,7 +191,7 @@
String snippet, boolean hasAttachment, Uri messageListUri, String senders,
int numMessages, int numDrafts, int sendingState, int priority, boolean read,
boolean starred, String folderList, String rawFolders, int convFlags,
- int personalLevel, boolean spam, boolean muted) {
+ int personalLevel, boolean spam, boolean muted, Uri accountUri) {
final Conversation conversation = new Conversation();
@@ -211,6 +216,7 @@
conversation.spam = spam;
conversation.muted = muted;
conversation.color = 0;
+ conversation.accountUri = accountUri;
return conversation;
}
diff --git a/src/com/android/mail/providers/MailAppProvider.java b/src/com/android/mail/providers/MailAppProvider.java
index f2d022f..d2a079b 100644
--- a/src/com/android/mail/providers/MailAppProvider.java
+++ b/src/com/android/mail/providers/MailAppProvider.java
@@ -16,6 +16,7 @@
package com.android.mail.providers;
+import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -459,6 +460,19 @@
return mSharedPrefs;
}
+ static public Account getAccountFromAccountUri(Uri accountUri) {
+ MailAppProvider provider = getInstance();
+ if (provider != null && provider.mAccountsFullyLoaded) {
+ synchronized(provider.mAccountCache) {
+ AccountCacheEntry entry = provider.mAccountCache.get(accountUri);
+ if (entry != null) {
+ return entry.mAccount;
+ }
+ }
+ }
+ return null;
+ }
+
@Override
public void onLoadComplete(Loader<Cursor> loader, Cursor data) {
if (data == null) {
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index 228530e..d5ef631 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -572,6 +572,12 @@
* Deletions in this folder can't be undone (could include archive if desirable)
*/
public static final int DELETE_ACTION_FINAL = 0x0200;
+ /**
+ * 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 class FolderColumns {
@@ -679,7 +685,8 @@
ConversationColumns.PERSONAL_LEVEL,
ConversationColumns.SPAM,
ConversationColumns.MUTED,
- ConversationColumns.COLOR
+ ConversationColumns.COLOR,
+ ConversationColumns.ACCOUNT_URI
};
// These column indexes only work when the caller uses the
@@ -705,6 +712,7 @@
public static final int CONVERSATION_IS_SPAM_COLUMN = 18;
public static final int CONVERSATION_MUTED_COLUMN = 19;
public static final int CONVERSATION_COLOR_COLUMN = 20;
+ public static final int CONVERSATION_ACCOUNT_URI_COLUMN = 21;
public static final class ConversationSendingState {
public static final int OTHER = 0;
@@ -833,6 +841,11 @@
*/
public static final String COLOR = "color";
+ /**
+ * This String column contains the Uri for this conversation's account
+ */
+ public static final String ACCOUNT_URI = "accountUri";
+
private ConversationColumns() {
}
}