Merge "PhotoViewer handles single URIs more robustly." into jb-ub-mail
diff --git a/res/values/constants.xml b/res/values/constants.xml
index ccf4f44..0b255ed 100644
--- a/res/values/constants.xml
+++ b/res/values/constants.xml
@@ -66,4 +66,7 @@
<!-- Number of decoded contact photo bitmaps retained in an LRU cache -->
<integer name="config_image_cache_max_bitmaps">24</integer>
+
+ <!-- Whether to display folder colors in the widget -->
+ <bool name="display_folder_colors_in_widget">false</bool>
</resources>
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() {
}
}
diff --git a/src/com/android/mail/widget/WidgetConversationViewBuilder.java b/src/com/android/mail/widget/WidgetConversationViewBuilder.java
index 59acd6e..3fe6d23 100644
--- a/src/com/android/mail/widget/WidgetConversationViewBuilder.java
+++ b/src/com/android/mail/widget/WidgetConversationViewBuilder.java
@@ -18,6 +18,11 @@
import com.android.mail.R;
import com.android.mail.providers.Account;
+import com.android.mail.providers.Folder;
+import com.android.mail.ui.FolderDisplayer;
+import com.android.mail.widget.WidgetConversationViewBuilder.WidgetFolderDisplayer;
+
+import java.util.Map;
import android.content.Context;
import android.content.res.Resources;
@@ -51,6 +56,64 @@
private static Bitmap ATTACHMENT;
private final Context mContext;
+ private WidgetFolderDisplayer mFolderDisplayer;
+
+ /**
+ * Label Displayer for Widget
+ */
+ protected static class WidgetFolderDisplayer extends FolderDisplayer {
+ public WidgetFolderDisplayer(Context context) {
+ super(context);
+ }
+
+ // Maximum number of folders we want to display
+ private static final int MAX_DISPLAYED_FOLDERS_COUNT = 3;
+
+ /*
+ * Load Conversation Labels
+ */
+ @Override
+ public void loadConversationFolders(String rawFolders, Folder ignoreFolder) {
+ super.loadConversationFolders(rawFolders, ignoreFolder);
+ }
+
+ private int getFolderViewId(int position) {
+ switch (position) {
+ case 0:
+ return R.id.widget_folder_0;
+ case 1:
+ return R.id.widget_folder_1;
+ case 2:
+ return R.id.widget_folder_2;
+ }
+ return 0;
+ }
+
+ /**
+ * Display folders
+ */
+ public void displayFolders(RemoteViews remoteViews) {
+ int displayedFolder = 0;
+ for (Folder folderValues : mFoldersSortedSet) {
+ int viewId = getFolderViewId(displayedFolder);
+ if (viewId == 0) {
+ continue;
+ }
+ remoteViews.setViewVisibility(viewId, View.VISIBLE);
+ int color[] = new int[] {folderValues.getBackgroundColor(mDefaultBgColor)};
+ Bitmap bitmap = Bitmap.createBitmap(color, 1, 1, Bitmap.Config.RGB_565);
+ remoteViews.setImageViewBitmap(viewId, bitmap);
+
+ if (++displayedFolder == MAX_DISPLAYED_FOLDERS_COUNT) {
+ break;
+ }
+ }
+
+ for (int i = displayedFolder; i < MAX_DISPLAYED_FOLDERS_COUNT; i++) {
+ remoteViews.setViewVisibility(getFolderViewId(i), View.GONE);
+ }
+ }
+ }
/*
* Get font sizes and bitmaps from Resources
@@ -94,9 +157,9 @@
/*
* Return the full View
*/
- public RemoteViews getStyledView(
- CharSequence senders, CharSequence status, CharSequence date, CharSequence subject,
- CharSequence snippet, String folders, boolean hasAttachments, boolean read) {
+ public RemoteViews getStyledView(CharSequence senders, CharSequence status, CharSequence date,
+ CharSequence subject, CharSequence snippet, String folders, boolean hasAttachments,
+ boolean read, Folder currentFolder) {
final boolean isUnread = !read;
@@ -159,6 +222,11 @@
remoteViews.setViewVisibility(R.id.widget_unread_background, View.GONE);
remoteViews.setViewVisibility(R.id.widget_read_background, View.VISIBLE);
}
+ if (mContext.getResources().getBoolean(R.bool.display_folder_colors_in_widget)) {
+ mFolderDisplayer = new WidgetFolderDisplayer(mContext);
+ mFolderDisplayer.loadConversationFolders(folders, currentFolder);
+ mFolderDisplayer.displayFolders(remoteViews);
+ }
return remoteViews;
}
diff --git a/src/com/android/mail/widget/WidgetService.java b/src/com/android/mail/widget/WidgetService.java
index bd50886..23dc6c7 100644
--- a/src/com/android/mail/widget/WidgetService.java
+++ b/src/com/android/mail/widget/WidgetService.java
@@ -64,7 +64,7 @@
/**
* Remote Views Factory for Mail Widget.
*/
- private static class MailFactory
+ protected static class MailFactory
implements RemoteViewsService.RemoteViewsFactory, OnLoadCompleteListener<Cursor> {
private static final int MAX_CONVERSATIONS_COUNT = 25;
private static final int MAX_SENDERS_LENGTH = 25;
@@ -91,7 +91,8 @@
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
mAccount = Account.newinstance(intent.getStringExtra(WidgetProvider.EXTRA_ACCOUNT));
mFolder = new Folder(intent.getStringExtra(WidgetProvider.EXTRA_FOLDER));
- mWidgetConversationViewBuilder = new WidgetConversationViewBuilder(mContext, mAccount);
+ mWidgetConversationViewBuilder = new WidgetConversationViewBuilder(context,
+ mAccount);
mResolver = context.getContentResolver();
mService = service;
}
@@ -221,8 +222,8 @@
// Load up our remote view.
RemoteViews remoteViews = mWidgetConversationViewBuilder.getStyledView(
senderBuilder, statusBuilder, date, filterTag(conversation.subject),
- conversation.snippet, conversation.folderList, conversation.hasAttachments,
- conversation.read);
+ conversation.snippet, conversation.rawFolders, conversation.hasAttachments,
+ conversation.read, mFolder);
// On click intent.
remoteViews.setOnClickFillInIntent(R.id.widget_conversation,