Remove widget views
The new widget UX allows for a single display mode for the widget. This can be configured when the widget is added or at a later time during widget re-configuration. We don't have the configuration activity (yet). We first need to restructure the widget to take a single account / mailbox combination. Hooking up the configuration activity will occur in a future CL. Change-Id: I38a5796c44938a6abd0d2bb50ac77241cc86a497
This commit is contained in:
parent
0f84ff2c08
commit
44f5cd67c9
|
@ -631,6 +631,10 @@ public abstract class EmailContent {
|
||||||
public static final String ALL_UNREAD_SELECTION =
|
public static final String ALL_UNREAD_SELECTION =
|
||||||
MessageColumns.FLAG_READ + "=0 AND " + ALL_INBOX_SELECTION;
|
MessageColumns.FLAG_READ + "=0 AND " + ALL_INBOX_SELECTION;
|
||||||
|
|
||||||
|
/** Selection to retrieve unread messages in "inbox" for one account */
|
||||||
|
public static final String PER_ACCOUNT_UNREAD_SELECTION =
|
||||||
|
ACCOUNT_KEY_SELECTION + " AND " + ALL_UNREAD_SELECTION;
|
||||||
|
|
||||||
/** Selection to retrieve all messages in "inbox" for one account */
|
/** Selection to retrieve all messages in "inbox" for one account */
|
||||||
public static final String PER_ACCOUNT_INBOX_SELECTION =
|
public static final String PER_ACCOUNT_INBOX_SELECTION =
|
||||||
ACCOUNT_KEY_SELECTION + " AND " + ALL_INBOX_SELECTION;
|
ACCOUNT_KEY_SELECTION + " AND " + ALL_INBOX_SELECTION;
|
||||||
|
|
|
@ -531,4 +531,4 @@ public class Mailbox extends EmailContent implements SyncColumns, MailboxColumns
|
||||||
return new Mailbox[size];
|
return new Mailbox[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class WidgetProvider extends AppWidgetProvider {
|
||||||
Log.d(EmailWidget.TAG, "onUpdate");
|
Log.d(EmailWidget.TAG, "onUpdate");
|
||||||
}
|
}
|
||||||
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
super.onUpdate(context, appWidgetManager, appWidgetIds);
|
||||||
WidgetManager.getInstance().getOrCreateWidgets(context, appWidgetIds);
|
WidgetManager.getInstance().createWidgets(context, appWidgetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -225,8 +225,5 @@ public class EmailBroadcastProcessorService extends IntentService {
|
||||||
// If the exchange service wasn't already running, starting it will cause exchange account
|
// If the exchange service wasn't already running, starting it will cause exchange account
|
||||||
// reconciliation to be performed. The service stops itself it there are no EAS accounts.
|
// reconciliation to be performed. The service stops itself it there are no EAS accounts.
|
||||||
ExchangeUtils.startExchangeService(this);
|
ExchangeUtils.startExchangeService(this);
|
||||||
|
|
||||||
// Let all of the widgets update
|
|
||||||
WidgetManager.getInstance().updateAllWidgets();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,15 +23,16 @@ import com.android.email.activity.MessageCompose;
|
||||||
import com.android.email.activity.UiUtilities;
|
import com.android.email.activity.UiUtilities;
|
||||||
import com.android.email.activity.Welcome;
|
import com.android.email.activity.Welcome;
|
||||||
import com.android.email.provider.WidgetProvider.WidgetService;
|
import com.android.email.provider.WidgetProvider.WidgetService;
|
||||||
|
import com.android.emailcommon.provider.EmailContent.Account;
|
||||||
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
||||||
import com.android.emailcommon.provider.EmailContent.Message;
|
import com.android.emailcommon.provider.EmailContent.Message;
|
||||||
import com.android.emailcommon.provider.Mailbox;
|
import com.android.emailcommon.provider.Mailbox;
|
||||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||||
import com.android.emailcommon.utility.Utility;
|
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.appwidget.AppWidgetManager;
|
import android.appwidget.AppWidgetManager;
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.CursorLoader;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.Loader;
|
import android.content.Loader;
|
||||||
import android.content.Loader.OnLoadCompleteListener;
|
import android.content.Loader.OnLoadCompleteListener;
|
||||||
|
@ -57,11 +58,8 @@ import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The email widget.
|
* The email widget.
|
||||||
*
|
* <p><em>NOTE</em>: All methods must be called on the UI thread so synchronization is NOT required
|
||||||
* Threading notes:
|
* in this class)
|
||||||
* - All methods must be called on the UI thread, except for {@link WidgetUpdater#doInBackground}.
|
|
||||||
* - {@link WidgetUpdater#doInBackground} must not read/write any members of {@link EmailWidget}.
|
|
||||||
* - (So no synchronizations are required in this class)
|
|
||||||
*/
|
*/
|
||||||
public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
OnLoadCompleteListener<Cursor> {
|
OnLoadCompleteListener<Cursor> {
|
||||||
|
@ -90,16 +88,22 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
private static final Uri COMMAND_URI = Uri.parse("widget://command");
|
private static final Uri COMMAND_URI = Uri.parse("widget://command");
|
||||||
|
|
||||||
// Command names and Uri's built upon COMMAND_URI
|
// Command names and Uri's built upon COMMAND_URI
|
||||||
private static final String COMMAND_NAME_SWITCH_LIST_VIEW = "switch_list_view";
|
|
||||||
private static final Uri COMMAND_URI_SWITCH_LIST_VIEW =
|
|
||||||
COMMAND_URI.buildUpon().appendPath(COMMAND_NAME_SWITCH_LIST_VIEW).build();
|
|
||||||
private static final String COMMAND_NAME_VIEW_MESSAGE = "view_message";
|
private static final String COMMAND_NAME_VIEW_MESSAGE = "view_message";
|
||||||
private static final Uri COMMAND_URI_VIEW_MESSAGE =
|
private static final Uri COMMAND_URI_VIEW_MESSAGE =
|
||||||
COMMAND_URI.buildUpon().appendPath(COMMAND_NAME_VIEW_MESSAGE).build();
|
COMMAND_URI.buildUpon().appendPath(COMMAND_NAME_VIEW_MESSAGE).build();
|
||||||
|
|
||||||
private static final int MAX_MESSAGE_LIST_COUNT = 25;
|
private static final int MAX_MESSAGE_LIST_COUNT = 25;
|
||||||
|
|
||||||
|
// TODO Temporary selection / projection to pick the first account defined. Remove once the
|
||||||
|
// account / mailbox picker activity is added
|
||||||
|
private static final String SORT_ID_ASCENDING = AccountColumns.ID + " ASC";
|
||||||
|
private static final String[] ID_NAME_PROJECTION =
|
||||||
|
{ AccountColumns.ID, AccountColumns.DISPLAY_NAME };
|
||||||
|
private static final int ID_NAME_COLUMN_ID = 0;
|
||||||
|
private static final int ID_NAME_COLUMN_NAME = 1;
|
||||||
|
|
||||||
private static String sSubjectSnippetDivider;
|
private static String sSubjectSnippetDivider;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private static String sConfigureText;
|
private static String sConfigureText;
|
||||||
private static int sSenderFontSize;
|
private static int sSenderFontSize;
|
||||||
private static int sSubjectFontSize;
|
private static int sSubjectFontSize;
|
||||||
|
@ -117,6 +121,10 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
private final EmailWidgetLoader mLoader;
|
private final EmailWidgetLoader mLoader;
|
||||||
private final ResourceHelper mResourceHelper;
|
private final ResourceHelper mResourceHelper;
|
||||||
|
|
||||||
|
private long mAccountId = Account.NO_ACCOUNT;
|
||||||
|
private long mMailboxId = Mailbox.NO_MAILBOX;
|
||||||
|
private String mAccountName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cursor for the messages, with some extra info such as the number of accounts.
|
* The cursor for the messages, with some extra info such as the number of accounts.
|
||||||
*
|
*
|
||||||
|
@ -125,9 +133,6 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
*/
|
*/
|
||||||
private EmailWidgetLoader.CursorWithCounts mCursor;
|
private EmailWidgetLoader.CursorWithCounts mCursor;
|
||||||
|
|
||||||
/** The current view type */
|
|
||||||
/* package */ WidgetView mWidgetView = WidgetView.UNINITIALIZED_VIEW;
|
|
||||||
|
|
||||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||||
|
|
||||||
public EmailWidget(Context context, int _widgetId) {
|
public EmailWidget(Context context, int _widgetId) {
|
||||||
|
@ -158,9 +163,23 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
// The default view is UNINITIALIZED_VIEW, and we switch to the next one, which should
|
// TODO By default, pick an account to display the widget for. This should all be removed
|
||||||
// be the initial view. (the first view shown to the user.)
|
// once the widget configuration activity is hooked up.
|
||||||
switchView();
|
CursorLoader accountLoader = new CursorLoader(
|
||||||
|
mContext, Account.CONTENT_URI, ID_NAME_PROJECTION, null, null, SORT_ID_ASCENDING);
|
||||||
|
accountLoader.registerListener(1, new OnLoadCompleteListener<Cursor>() {
|
||||||
|
@Override
|
||||||
|
public void onLoadComplete(android.content.Loader<Cursor> loader, Cursor data) {
|
||||||
|
long accountId = Account.NO_ACCOUNT;
|
||||||
|
String accountName = null;
|
||||||
|
if (data != null && data.moveToFirst()) {
|
||||||
|
accountId = data.getLong(ID_NAME_COLUMN_ID);
|
||||||
|
accountName = data.getString(ID_NAME_COLUMN_NAME);
|
||||||
|
}
|
||||||
|
loadView(accountId, accountName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
accountLoader.startLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCursorValid() {
|
private boolean isCursorValid() {
|
||||||
|
@ -174,7 +193,6 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
|
public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
|
||||||
// Save away the cursor
|
// Save away the cursor
|
||||||
mCursor = (EmailWidgetLoader.CursorWithCounts) cursor;
|
mCursor = (EmailWidgetLoader.CursorWithCounts) cursor;
|
||||||
mWidgetView = mLoader.getLoadingWidgetView();
|
|
||||||
|
|
||||||
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.widget);
|
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.widget);
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
@ -187,25 +205,10 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
* Start loading the data. At this point nothing on the widget changes -- the current view
|
* Start loading the data. At this point nothing on the widget changes -- the current view
|
||||||
* will remain valid until the loader loads the latest data.
|
* will remain valid until the loader loads the latest data.
|
||||||
*/
|
*/
|
||||||
private void loadView(WidgetView view) {
|
private void loadView(long accountId, String accountName) {
|
||||||
mLoader.load(view);
|
mAccountId = accountId;
|
||||||
}
|
mAccountName = accountName;
|
||||||
|
mLoader.load(mAccountId, mMailboxId);
|
||||||
/**
|
|
||||||
* Convenience method for creating an onClickPendingIntent that executes a command via
|
|
||||||
* our command Uri. Used for the "next view" command; appends the widget id to the command
|
|
||||||
* Uri.
|
|
||||||
*
|
|
||||||
* @param views The RemoteViews we're inflating
|
|
||||||
* @param buttonId the id of the button view
|
|
||||||
* @param data the command Uri
|
|
||||||
*/
|
|
||||||
private void setCommandIntent(RemoteViews views, int buttonId, Uri data) {
|
|
||||||
Intent intent = new Intent(mContext, WidgetService.class);
|
|
||||||
intent.setDataAndType(ContentUris.withAppendedId(data, mWidgetId), WIDGET_DATA_MIME_TYPE);
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, intent,
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
views.setOnClickPendingIntent(buttonId, pendingIntent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,12 +266,6 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
if (EmailWidget.COMMAND_NAME_VIEW_MESSAGE.equals(command)) {
|
if (EmailWidget.COMMAND_NAME_VIEW_MESSAGE.equals(command)) {
|
||||||
// "view", <message id>, <mailbox id>
|
// "view", <message id>, <mailbox id>
|
||||||
openMessage(context, Long.parseLong(pathSegments.get(2)), arg1);
|
openMessage(context, Long.parseLong(pathSegments.get(2)), arg1);
|
||||||
} else if (EmailWidget.COMMAND_NAME_SWITCH_LIST_VIEW.equals(command)) {
|
|
||||||
// "next_view", <widget id>
|
|
||||||
EmailWidget widget = WidgetManager.getInstance().get((int)arg1);
|
|
||||||
if (widget != null) {
|
|
||||||
widget.switchView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// Shouldn't happen as we construct all of the Uri's
|
// Shouldn't happen as we construct all of the Uri's
|
||||||
|
@ -279,7 +276,7 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
|
|
||||||
private static void openMessage(final Context context, final long mailboxId,
|
private static void openMessage(final Context context, final long mailboxId,
|
||||||
final long messageId) {
|
final long messageId) {
|
||||||
Utility.runAsync(new Runnable() {
|
EmailAsyncTask.runAsyncParallel(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
|
Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
|
||||||
|
@ -292,8 +289,10 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
|
|
||||||
private void setupTitleAndCount(RemoteViews views) {
|
private void setupTitleAndCount(RemoteViews views) {
|
||||||
// Set up the title (view type + count of messages)
|
// Set up the title (view type + count of messages)
|
||||||
views.setTextViewText(R.id.widget_title, mWidgetView.getTitle(mContext));
|
views.setTextViewText(R.id.widget_title, mAccountName);
|
||||||
views.setTextViewText(R.id.widget_tap, sConfigureText);
|
// TODO Temporary UX; need to make this visible and create the correct UX
|
||||||
|
//views.setTextViewText(R.id.widget_tap, sConfigureText);
|
||||||
|
views.setViewVisibility(R.id.widget_tap, View.INVISIBLE);
|
||||||
String count = "";
|
String count = "";
|
||||||
if (isCursorValid()) {
|
if (isCursorValid()) {
|
||||||
count = UiUtilities.getMessageCountForUi(mContext, mCursor.getMessageCount(), false);
|
count = UiUtilities.getMessageCountForUi(mContext, mCursor.getMessageCount(), false);
|
||||||
|
@ -317,11 +316,11 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
Intent intent = new Intent(mContext, WidgetService.class);
|
Intent intent = new Intent(mContext, WidgetService.class);
|
||||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId);
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId);
|
||||||
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
|
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
|
||||||
views.setRemoteAdapter(mWidgetId, R.id.message_list, intent);
|
views.setRemoteAdapter(R.id.message_list, intent);
|
||||||
|
|
||||||
setupTitleAndCount(views);
|
setupTitleAndCount(views);
|
||||||
|
|
||||||
if (!isCursorValid() || mCursor.getAccountCount() == 0) {
|
if (!isCursorValid() || mAccountId == Account.NO_ACCOUNT) {
|
||||||
// Hide compose icon & show "touch to configure" text
|
// Hide compose icon & show "touch to configure" text
|
||||||
views.setViewVisibility(R.id.widget_compose, View.INVISIBLE);
|
views.setViewVisibility(R.id.widget_compose, View.INVISIBLE);
|
||||||
views.setViewVisibility(R.id.message_list, View.GONE);
|
views.setViewVisibility(R.id.message_list, View.GONE);
|
||||||
|
@ -338,8 +337,6 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
intent = MessageCompose.getMessageComposeIntent(mContext, -1);
|
intent = MessageCompose.getMessageComposeIntent(mContext, -1);
|
||||||
setActivityIntent(views, R.id.widget_compose, intent);
|
setActivityIntent(views, R.id.widget_compose, intent);
|
||||||
}
|
}
|
||||||
// Create click intent for "view rotation" target
|
|
||||||
setCommandIntent(views, R.id.widget_logo, COMMAND_URI_SWITCH_LIST_VIEW);
|
|
||||||
|
|
||||||
// Use a bare intent for our template; we need to fill everything in
|
// Use a bare intent for our template; we need to fill everything in
|
||||||
intent = new Intent(mContext, WidgetService.class);
|
intent = new Intent(mContext, WidgetService.class);
|
||||||
|
@ -452,7 +449,7 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
views.setViewVisibility(R.id.widget_attachment,
|
views.setViewVisibility(R.id.widget_attachment,
|
||||||
hasAttachment ? View.VISIBLE : View.GONE);
|
hasAttachment ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
if (mCursor.getAccountCount() <= 1 || mWidgetView.isPerAccount()) {
|
if (mAccountId != Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||||
views.setViewVisibility(R.id.color_chip, View.INVISIBLE);
|
views.setViewVisibility(R.id.color_chip, View.INVISIBLE);
|
||||||
} else {
|
} else {
|
||||||
long accountId = mCursor.getLong(EmailWidgetLoader.WIDGET_COLUMN_ACCOUNT_KEY);
|
long accountId = mCursor.getLong(EmailWidgetLoader.WIDGET_COLUMN_ACCOUNT_KEY);
|
||||||
|
@ -513,7 +510,6 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
if (mLoader != null) {
|
if (mLoader != null) {
|
||||||
mLoader.reset();
|
mLoader.reset();
|
||||||
}
|
}
|
||||||
WidgetManager.getInstance().remove(mWidgetId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -522,57 +518,14 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
|
||||||
mLoader.reset();
|
mLoader.reset();
|
||||||
}
|
}
|
||||||
mTaskTracker.cancellAllInterrupt();
|
mTaskTracker.cancellAllInterrupt();
|
||||||
WidgetManager.getInstance().remove(mWidgetId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Update the widget. If the current view is invalid, switch to the next view, then update.
|
public String toString() {
|
||||||
*/
|
return "View=" + mAccountName;
|
||||||
/* package */ void validateAndUpdate() {
|
|
||||||
new WidgetUpdater(this, false).cancelPreviousAndExecuteParallel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switch to the next view.
|
|
||||||
*/
|
|
||||||
/* package */ void switchView() {
|
|
||||||
new WidgetUpdater(this, true).cancelPreviousAndExecuteParallel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the widget. If {@code switchToNextView} is set true, or the current view is invalid,
|
|
||||||
* switch to the next view.
|
|
||||||
*/
|
|
||||||
private static class WidgetUpdater extends EmailAsyncTask<Void, Void, WidgetView> {
|
|
||||||
private final EmailWidget mParent;
|
|
||||||
private final WidgetView mCurrentView;
|
|
||||||
private final boolean mSwitchToNextView;
|
|
||||||
|
|
||||||
public WidgetUpdater(EmailWidget parent, boolean switchToNextView) {
|
|
||||||
super(parent.mTaskTracker);
|
|
||||||
mParent = parent;
|
|
||||||
mCurrentView = mParent.mWidgetView;
|
|
||||||
mSwitchToNextView = switchToNextView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected WidgetView doInBackground(Void... params) {
|
|
||||||
if (mSwitchToNextView || !mCurrentView.isValid(mParent.mContext)) {
|
|
||||||
return mCurrentView.getNext(mParent.mContext);
|
|
||||||
} else {
|
|
||||||
return mCurrentView; // Reload the same view.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(WidgetView nextView) {
|
|
||||||
if (nextView != null) {
|
|
||||||
mParent.loadView(nextView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ package com.android.email.widget;
|
||||||
|
|
||||||
import com.android.email.data.ThrottlingCursorLoader;
|
import com.android.email.data.ThrottlingCursorLoader;
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
import com.android.emailcommon.provider.EmailContent;
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Message;
|
import com.android.emailcommon.provider.EmailContent.Message;
|
||||||
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
||||||
|
import com.android.emailcommon.provider.Mailbox;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
@ -35,7 +35,7 @@ import android.database.CursorWrapper;
|
||||||
* It's currently just the same as the message count, but this will be updated to the unread
|
* It's currently just the same as the message count, but this will be updated to the unread
|
||||||
* counts for inboxes.
|
* counts for inboxes.
|
||||||
*/
|
*/
|
||||||
/* package */ class EmailWidgetLoader extends ThrottlingCursorLoader {
|
class EmailWidgetLoader extends ThrottlingCursorLoader {
|
||||||
private static final String SORT_TIMESTAMP_DESCENDING = MessageColumns.TIMESTAMP + " DESC";
|
private static final String SORT_TIMESTAMP_DESCENDING = MessageColumns.TIMESTAMP + " DESC";
|
||||||
|
|
||||||
// The projection to be used by the WidgetLoader
|
// The projection to be used by the WidgetLoader
|
||||||
|
@ -57,23 +57,20 @@ import android.database.CursorWrapper;
|
||||||
public static final int WIDGET_COLUMN_ACCOUNT_KEY = 9;
|
public static final int WIDGET_COLUMN_ACCOUNT_KEY = 9;
|
||||||
public static final int WIDGET_COLUMN_FLAGS = 10;
|
public static final int WIDGET_COLUMN_FLAGS = 10;
|
||||||
|
|
||||||
|
private long mAccountId;
|
||||||
|
private long mMailboxId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actual data returned by this loader.
|
* The actual data returned by this loader.
|
||||||
*/
|
*/
|
||||||
public static class CursorWithCounts extends CursorWrapper {
|
static class CursorWithCounts extends CursorWrapper {
|
||||||
private final int mAccountCount;
|
|
||||||
private final int mMessageCount;
|
private final int mMessageCount;
|
||||||
|
|
||||||
public CursorWithCounts(Cursor cursor, int accountCount, int messageCount) {
|
public CursorWithCounts(Cursor cursor, int messageCount) {
|
||||||
super(cursor);
|
super(cursor);
|
||||||
mAccountCount = accountCount;
|
|
||||||
mMessageCount = messageCount;
|
mMessageCount = messageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAccountCount() {
|
|
||||||
return mAccountCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The count that should be shown on the widget header.
|
* @return The count that should be shown on the widget header.
|
||||||
* Note depending on the view, it may be the unread count, which is different from
|
* Note depending on the view, it may be the unread count, which is different from
|
||||||
|
@ -86,9 +83,7 @@ import android.database.CursorWrapper;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
private WidgetView mLoadingWidgetView;
|
EmailWidgetLoader(Context context) {
|
||||||
|
|
||||||
public EmailWidgetLoader(Context context) {
|
|
||||||
super(context, Message.CONTENT_URI, WIDGET_PROJECTION, null,
|
super(context, Message.CONTENT_URI, WIDGET_PROJECTION, null,
|
||||||
null, SORT_TIMESTAMP_DESCENDING);
|
null, SORT_TIMESTAMP_DESCENDING);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
@ -101,17 +96,17 @@ import android.database.CursorWrapper;
|
||||||
// Reset the notification Uri to our Message table notifier URI
|
// Reset the notification Uri to our Message table notifier URI
|
||||||
messagesCursor.setNotificationUri(mContext.getContentResolver(), Message.NOTIFIER_URI);
|
messagesCursor.setNotificationUri(mContext.getContentResolver(), Message.NOTIFIER_URI);
|
||||||
|
|
||||||
final int accountCount = EmailContent.count(mContext, Account.CONTENT_URI);
|
|
||||||
|
|
||||||
final int messageCount;
|
final int messageCount;
|
||||||
if (mLoadingWidgetView.useUnreadCount()) {
|
if (mMailboxId != Mailbox.QUERY_ALL_FAVORITES) {
|
||||||
messageCount = mLoadingWidgetView.getUnreadCount(mContext);
|
String selection = "(" + getSelection() + " ) AND " + MessageColumns.FLAG_READ + " = 0";
|
||||||
|
messageCount = EmailContent.count(mContext, Message.CONTENT_URI, selection,
|
||||||
|
getSelectionArgs());
|
||||||
} else {
|
} else {
|
||||||
// Just use the number of all messages shown.
|
// Just use the number of all messages shown.
|
||||||
messageCount = messagesCursor.getCount();
|
messageCount = messagesCursor.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CursorWithCounts(messagesCursor, accountCount, messageCount);
|
return new CursorWithCounts(messagesCursor, messageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,22 +114,15 @@ import android.database.CursorWrapper;
|
||||||
*
|
*
|
||||||
* Must be called from the UI thread
|
* Must be called from the UI thread
|
||||||
*
|
*
|
||||||
* @param view the current ViewType
|
* @param accountId
|
||||||
|
* @param mailboxId
|
||||||
*/
|
*/
|
||||||
public void load(WidgetView view) {
|
void load(long accountId, long mailboxId) {
|
||||||
reset();
|
reset();
|
||||||
mLoadingWidgetView = view;
|
mAccountId = accountId;
|
||||||
setSelection(view.getSelection());
|
mMailboxId = mailboxId;
|
||||||
setSelectionArgs(view.getSelectionArgs());
|
setSelection(Message.PER_ACCOUNT_UNREAD_SELECTION);
|
||||||
|
setSelectionArgs(new String[]{ Long.toString(mAccountId) });
|
||||||
startLoading();
|
startLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the {@link WidgetView} that is (being) loaded.
|
|
||||||
*
|
|
||||||
* Must be called from the UI thread
|
|
||||||
*/
|
|
||||||
public WidgetView getLoadingWidgetView() {
|
|
||||||
return mLoadingWidgetView;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,19 +43,9 @@ public class WidgetManager {
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public synchronized void createWidgets(Context context, int[] widgetIds) {
|
||||||
* Updates all active widgets. If no widgets are active, does nothing.
|
|
||||||
*/
|
|
||||||
public synchronized void updateAllWidgets() {
|
|
||||||
for (EmailWidget widget: mWidgets.values()) {
|
|
||||||
// Anything could have changed; update widget & validate the current view
|
|
||||||
widget.validateAndUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void getOrCreateWidgets(Context context, int[] widgetIds) {
|
|
||||||
for (int widgetId : widgetIds) {
|
for (int widgetId : widgetIds) {
|
||||||
getOrCreateWidget(context, widgetId).validateAndUpdate();
|
getOrCreateWidget(context, widgetId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,10 +57,11 @@ public class WidgetManager {
|
||||||
// Stop loading and remove the widget from the map
|
// Stop loading and remove the widget from the map
|
||||||
widget.onDeleted();
|
widget.onDeleted();
|
||||||
}
|
}
|
||||||
|
remove(widgetId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmailWidget getOrCreateWidget(Context context, int widgetId) {
|
public synchronized EmailWidget getOrCreateWidget(Context context, int widgetId) {
|
||||||
EmailWidget widget = WidgetManager.getInstance().get(widgetId);
|
EmailWidget widget = WidgetManager.getInstance().get(widgetId);
|
||||||
if (widget == null) {
|
if (widget == null) {
|
||||||
if (Email.DEBUG) {
|
if (Email.DEBUG) {
|
||||||
|
@ -83,15 +74,15 @@ public class WidgetManager {
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmailWidget get(int widgetId) {
|
private EmailWidget get(int widgetId) {
|
||||||
return mWidgets.get(widgetId);
|
return mWidgets.get(widgetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void put(int widgetId, EmailWidget widget) {
|
private void put(int widgetId, EmailWidget widget) {
|
||||||
mWidgets.put(widgetId, widget);
|
mWidgets.put(widgetId, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void remove(int widgetId) {
|
private void remove(int widgetId) {
|
||||||
mWidgets.remove(widgetId);
|
mWidgets.remove(widgetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +90,7 @@ public class WidgetManager {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (EmailWidget widget : mWidgets.values()) {
|
for (EmailWidget widget : mWidgets.values()) {
|
||||||
writer.println("Widget #" + (++n));
|
writer.println("Widget #" + (++n));
|
||||||
writer.println(" View=" + widget.mWidgetView);
|
writer.println(" " + widget.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,219 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2011 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.email.widget;
|
|
||||||
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Message;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
|
||||||
import com.android.emailcommon.utility.Utility;
|
|
||||||
|
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the "view" of the widget.
|
|
||||||
*
|
|
||||||
* It's a {@link ViewType} + mutable fields. (e.g. account id/name)
|
|
||||||
*/
|
|
||||||
/* package */ class WidgetView {
|
|
||||||
private static final String SORT_ID_ASCENDING = AccountColumns.ID + " ASC";
|
|
||||||
private static final String[] ID_NAME_PROJECTION = {Account.RECORD_ID, Account.DISPLAY_NAME};
|
|
||||||
private static final int ID_NAME_COLUMN_ID = 0;
|
|
||||||
private static final int ID_NAME_COLUMN_NAME = 1;
|
|
||||||
|
|
||||||
private static enum ViewType {
|
|
||||||
TYPE_ALL_UNREAD(false, Message.ALL_UNREAD_SELECTION, R.string.widget_unread, false),
|
|
||||||
TYPE_ALL_STARRED(false, Message.ALL_FAVORITE_SELECTION, R.string.widget_starred, false),
|
|
||||||
TYPE_ALL_INBOX(false, Message.ALL_INBOX_SELECTION, R.string.widget_all_mail, true),
|
|
||||||
TYPE_ACCOUNT_INBOX(true, Message.PER_ACCOUNT_INBOX_SELECTION, 0, true) {
|
|
||||||
@Override public String getTitle(Context context, String accountName) {
|
|
||||||
return accountName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String[] getSelectionArgs(long accountId) {
|
|
||||||
return new String[]{Long.toString(accountId)};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final boolean mIsPerAccount;
|
|
||||||
private final String mSelection;
|
|
||||||
private final int mTitleResource;
|
|
||||||
private final boolean mUseUnreadCount;
|
|
||||||
|
|
||||||
ViewType(boolean isPerAccount, String selection, int titleResource,
|
|
||||||
boolean useUnreadCount) {
|
|
||||||
mIsPerAccount = isPerAccount;
|
|
||||||
mSelection = selection;
|
|
||||||
mTitleResource = titleResource;
|
|
||||||
mUseUnreadCount = useUnreadCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle(Context context, String accountName) {
|
|
||||||
return context.getString(mTitleResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSelection() {
|
|
||||||
return mSelection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getSelectionArgs(long accountId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package */ static final WidgetView ALL_UNREAD = new WidgetView(ViewType.TYPE_ALL_UNREAD);
|
|
||||||
/* package */ static final WidgetView ALL_STARRED = new WidgetView(ViewType.TYPE_ALL_STARRED);
|
|
||||||
/* package */ static final WidgetView ALL_INBOX = new WidgetView(ViewType.TYPE_ALL_INBOX);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The initial view will be the *next* of ALL_STARRED -- see {@link #getNext}.
|
|
||||||
*/
|
|
||||||
public static final WidgetView UNINITIALIZED_VIEW = ALL_STARRED;
|
|
||||||
|
|
||||||
private final ViewType mViewType;
|
|
||||||
/** Account ID -- set only when isPerAccount */
|
|
||||||
private final long mAccountId;
|
|
||||||
/** Account name -- set only when isPerAccount */
|
|
||||||
private final String mAccountName;
|
|
||||||
|
|
||||||
private WidgetView(ViewType viewType) {
|
|
||||||
this(viewType, 0, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private WidgetView(ViewType viewType, long accountId, String accountName) {
|
|
||||||
mViewType = viewType;
|
|
||||||
mAccountId = accountId;
|
|
||||||
mAccountName = accountName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPerAccount() {
|
|
||||||
return mViewType.mIsPerAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle(Context context) {
|
|
||||||
return mViewType.getTitle(context, mAccountName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean useUnreadCount() {
|
|
||||||
return mViewType.mUseUnreadCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSelection() {
|
|
||||||
return mViewType.getSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getSelectionArgs() {
|
|
||||||
return mViewType.getSelectionArgs(mAccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switch to the "next" view.
|
|
||||||
*
|
|
||||||
* Views rotate in this order:
|
|
||||||
* - {@link #ALL_STARRED}
|
|
||||||
* - {@link #ALL_INBOX} -- this will be skipped if # of accounts <= 1
|
|
||||||
* - Inbox for account 1
|
|
||||||
* - Inbox for account 2
|
|
||||||
* - :
|
|
||||||
* - {@link #ALL_UNREAD}
|
|
||||||
* - Go back to {@link #ALL_STARRED}.
|
|
||||||
*
|
|
||||||
* Note the initial view is always the next of {@link #ALL_STARRED}.
|
|
||||||
*/
|
|
||||||
public WidgetView getNext(Context context) {
|
|
||||||
if (mViewType == ViewType.TYPE_ALL_UNREAD) {
|
|
||||||
return ALL_STARRED;
|
|
||||||
}
|
|
||||||
if (mViewType == ViewType.TYPE_ALL_STARRED) {
|
|
||||||
// If we're in starred and there is more than one account, go to "all mail"
|
|
||||||
// Otherwise, fall through to the accounts themselves
|
|
||||||
if (EmailContent.count(context, Account.CONTENT_URI) > 1) {
|
|
||||||
return ALL_INBOX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final long nextAccountIdStart;
|
|
||||||
if (mViewType == ViewType.TYPE_ALL_INBOX) {
|
|
||||||
nextAccountIdStart = -1;
|
|
||||||
} else { // TYPE_ACCOUNT_INBOX
|
|
||||||
nextAccountIdStart = mAccountId + 1;
|
|
||||||
}
|
|
||||||
Cursor c = context.getContentResolver().query(Account.CONTENT_URI, ID_NAME_PROJECTION,
|
|
||||||
"_id>=?", new String[] {Long.toString(nextAccountIdStart)}, SORT_ID_ASCENDING);
|
|
||||||
|
|
||||||
final long nextAccountId;
|
|
||||||
final String nextAccountName;
|
|
||||||
try {
|
|
||||||
if (c.moveToFirst()) {
|
|
||||||
return new WidgetView(ViewType.TYPE_ACCOUNT_INBOX, c.getLong(ID_NAME_COLUMN_ID),
|
|
||||||
c.getString(ID_NAME_COLUMN_NAME));
|
|
||||||
} else {
|
|
||||||
return ALL_UNREAD;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the current view is valid. The following rules determine if a view is
|
|
||||||
* considered valid:
|
|
||||||
* 1. {@link ViewType#TYPE_ALL_STARRED} and {@link ViewType#TYPE_ALL_UNREAD} are always
|
|
||||||
* valid.
|
|
||||||
* 2. If the view is {@link ViewType#TYPE_ALL_INBOX}, returns <code>true</code> if more than
|
|
||||||
* one account is defined. Otherwise, returns <code>false</code>.
|
|
||||||
* 3. If the view is {@link ViewType#TYPE_ACCOUNT_INBOX}, returns <code>true</code> if the
|
|
||||||
* account is defined. Otherwise, returns <code>false</code>.
|
|
||||||
*/
|
|
||||||
public boolean isValid(Context context) {
|
|
||||||
switch(mViewType) {
|
|
||||||
case TYPE_ALL_INBOX:
|
|
||||||
// "all inbox" is valid only if there is more than one account
|
|
||||||
return (EmailContent.count(context, Account.CONTENT_URI) > 1);
|
|
||||||
case TYPE_ACCOUNT_INBOX:
|
|
||||||
// Ensure current account still exists
|
|
||||||
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId);
|
|
||||||
return Utility.getFirstRowLong(context, uri,
|
|
||||||
EmailContent.ID_PROJECTION, null, null, null,
|
|
||||||
EmailContent.ID_PROJECTION_COLUMN, null) != null;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return unread message count using the selection.
|
|
||||||
*/
|
|
||||||
public int getUnreadCount(Context context) {
|
|
||||||
String selection = "(" + getSelection() + " ) AND " + MessageColumns.FLAG_READ + " = 0";
|
|
||||||
return EmailContent.count(context, Message.CONTENT_URI, selection,
|
|
||||||
getSelectionArgs());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder("WidgetView:type=");
|
|
||||||
sb.append(mViewType);
|
|
||||||
sb.append(" account=");
|
|
||||||
sb.append(mAccountId);
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
/* Copyright (C) 2011 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.email.widget;
|
|
||||||
|
|
||||||
import com.android.email.provider.EmailProvider;
|
|
||||||
import com.android.email.provider.ProviderTestUtils;
|
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Message;
|
|
||||||
import com.android.emailcommon.provider.Mailbox;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.test.ProviderTestCase2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests of EmailWidget
|
|
||||||
*
|
|
||||||
* You can run this entire test case with:
|
|
||||||
* runtest -c com.android.email.widget.WidgetView email
|
|
||||||
*/
|
|
||||||
public class WidgetViewTests extends ProviderTestCase2<EmailProvider> {
|
|
||||||
private Context mMockContext;
|
|
||||||
|
|
||||||
public WidgetViewTests() {
|
|
||||||
super(EmailProvider.class, EmailContent.AUTHORITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
mMockContext = getMockContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getMessageCount(WidgetView view) {
|
|
||||||
return EmailContent.count(mMockContext, Message.CONTENT_URI,
|
|
||||||
view.getSelection(), view.getSelectionArgs());
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getUnreadCount(WidgetView view) {
|
|
||||||
return view.getUnreadCount(mMockContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read,
|
|
||||||
int flagLoaded) {
|
|
||||||
Message message = ProviderTestUtils.setupMessage(
|
|
||||||
"1", b.mAccountKey, b.mId, true, false, c, starred, read);
|
|
||||||
message.mFlagLoaded = flagLoaded;
|
|
||||||
message.save(c);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testGetNext() {
|
|
||||||
// Test with 1 account.
|
|
||||||
final Account a1 = ProviderTestUtils.setupAccount("account1", true, mMockContext);
|
|
||||||
|
|
||||||
WidgetView view = WidgetView.ALL_UNREAD;
|
|
||||||
|
|
||||||
// all unread -> all starred
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertEquals(WidgetView.ALL_STARRED, view);
|
|
||||||
|
|
||||||
// all starred -> account 1 inbox
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertTrue(view.isPerAccount());
|
|
||||||
assertEquals(Long.toString(a1.mId), view.getSelectionArgs()[0]);
|
|
||||||
|
|
||||||
// account 1 inbox -> all unread
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertEquals(WidgetView.ALL_UNREAD, view);
|
|
||||||
|
|
||||||
// Next, test with 2 accounts.
|
|
||||||
final Account a2 = ProviderTestUtils.setupAccount("account2", true, mMockContext);
|
|
||||||
|
|
||||||
// Still all unread
|
|
||||||
assertEquals(WidgetView.ALL_UNREAD, view);
|
|
||||||
|
|
||||||
// all unread -> all starred
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertEquals(WidgetView.ALL_STARRED, view);
|
|
||||||
|
|
||||||
// all starred -> all inboxes, as there are more than 1 account.
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertEquals(WidgetView.ALL_INBOX, view);
|
|
||||||
|
|
||||||
// all inbox -> account 1 inbox
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertTrue(view.isPerAccount());
|
|
||||||
assertEquals(Long.toString(a1.mId), view.getSelectionArgs()[0]);
|
|
||||||
|
|
||||||
// account 1 inbox -> account 2 inbox
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertTrue(view.isPerAccount());
|
|
||||||
assertEquals(Long.toString(a2.mId), view.getSelectionArgs()[0]);
|
|
||||||
|
|
||||||
// account 2 inbox -> all unread
|
|
||||||
view = view.getNext(mMockContext);
|
|
||||||
assertEquals(WidgetView.ALL_UNREAD, view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsValid() {
|
|
||||||
// with 0 accounts
|
|
||||||
assertTrue(WidgetView.ALL_UNREAD.isValid(mMockContext));
|
|
||||||
assertTrue(WidgetView.ALL_STARRED.isValid(mMockContext));
|
|
||||||
assertFalse(WidgetView.ALL_INBOX.isValid(mMockContext));
|
|
||||||
|
|
||||||
// Test with 1 account.
|
|
||||||
final Account a1 = ProviderTestUtils.setupAccount("account1", true, mMockContext);
|
|
||||||
assertTrue(WidgetView.ALL_UNREAD.isValid(mMockContext));
|
|
||||||
assertTrue(WidgetView.ALL_STARRED.isValid(mMockContext));
|
|
||||||
assertFalse(WidgetView.ALL_INBOX.isValid(mMockContext)); // only 1 account -- still invalid
|
|
||||||
|
|
||||||
final WidgetView account1View = WidgetView.ALL_INBOX.getNext(mMockContext);
|
|
||||||
assertEquals(Long.toString(a1.mId), account1View.getSelectionArgs()[0]);
|
|
||||||
assertTrue(account1View.isValid(mMockContext));
|
|
||||||
|
|
||||||
// Test with 2 accounts.
|
|
||||||
final Account a2 = ProviderTestUtils.setupAccount("account2", true, mMockContext);
|
|
||||||
assertTrue(WidgetView.ALL_UNREAD.isValid(mMockContext));
|
|
||||||
assertTrue(WidgetView.ALL_STARRED.isValid(mMockContext));
|
|
||||||
assertTrue(WidgetView.ALL_INBOX.isValid(mMockContext)); // now it's valid
|
|
||||||
|
|
||||||
final WidgetView account2View = account1View.getNext(mMockContext);
|
|
||||||
assertEquals(Long.toString(a2.mId), account2View.getSelectionArgs()[0]);
|
|
||||||
assertTrue(account2View.isValid(mMockContext));
|
|
||||||
|
|
||||||
// Remove account 1
|
|
||||||
ProviderTestUtils.deleteAccount(mMockContext, a1.mId);
|
|
||||||
|
|
||||||
assertTrue(WidgetView.ALL_UNREAD.isValid(mMockContext));
|
|
||||||
assertTrue(WidgetView.ALL_STARRED.isValid(mMockContext));
|
|
||||||
assertFalse(WidgetView.ALL_INBOX.isValid(mMockContext)); // only 1 account -- now invalid
|
|
||||||
|
|
||||||
assertFalse(account1View.isValid(mMockContext));
|
|
||||||
assertTrue(account2View.isValid(mMockContext));
|
|
||||||
|
|
||||||
// Remove account 2
|
|
||||||
ProviderTestUtils.deleteAccount(mMockContext, a2.mId);
|
|
||||||
|
|
||||||
assertTrue(WidgetView.ALL_UNREAD.isValid(mMockContext));
|
|
||||||
assertTrue(WidgetView.ALL_STARRED.isValid(mMockContext));
|
|
||||||
assertFalse(WidgetView.ALL_INBOX.isValid(mMockContext)); // still invalid
|
|
||||||
|
|
||||||
assertFalse(account1View.isValid(mMockContext));
|
|
||||||
assertFalse(account2View.isValid(mMockContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the message counts returned by the ViewType selectors.
|
|
||||||
*/
|
|
||||||
public void testCursorCount() {
|
|
||||||
// Create 2 accounts
|
|
||||||
Account a1 = ProviderTestUtils.setupAccount("account1", true, mMockContext);
|
|
||||||
Account a2 = ProviderTestUtils.setupAccount("account2", true, mMockContext);
|
|
||||||
|
|
||||||
// Create 2 mailboxes for each account
|
|
||||||
Mailbox b11 = ProviderTestUtils.setupMailbox(
|
|
||||||
"box11", a1.mId, true, mMockContext, Mailbox.TYPE_INBOX);
|
|
||||||
Mailbox b12 = ProviderTestUtils.setupMailbox(
|
|
||||||
"box12", a1.mId, true, mMockContext, Mailbox.TYPE_OUTBOX);
|
|
||||||
Mailbox b21 = ProviderTestUtils.setupMailbox(
|
|
||||||
"box21", a2.mId, true, mMockContext, Mailbox.TYPE_INBOX);
|
|
||||||
Mailbox b22 = ProviderTestUtils.setupMailbox(
|
|
||||||
"box22", a2.mId, true, mMockContext, Mailbox.TYPE_OUTBOX);
|
|
||||||
Mailbox b2t = ProviderTestUtils.setupMailbox(
|
|
||||||
"box2T", a2.mId, true, mMockContext, Mailbox.TYPE_TRASH);
|
|
||||||
|
|
||||||
// Create some messages
|
|
||||||
// b11 (account 1, inbox): 2 messages
|
|
||||||
// star read
|
|
||||||
Message m11a = createMessage(mMockContext, b11, true, false, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message m11b = createMessage(mMockContext, b11, false, false, Message.FLAG_LOADED_UNLOADED);
|
|
||||||
|
|
||||||
// b12 (account 1, outbox): 2 messages
|
|
||||||
Message m12a = createMessage(mMockContext, b12, false, false, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message m12b = createMessage(mMockContext, b12, true, true, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
|
|
||||||
// b21 (account 2, inbox): 4 messages
|
|
||||||
Message m21a = createMessage(mMockContext, b21, false, false, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message m21b = createMessage(mMockContext, b21, false, true, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message m21c = createMessage(mMockContext, b21, true, true, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message m21d = createMessage(mMockContext, b21, true, true, Message.FLAG_LOADED_UNLOADED);
|
|
||||||
|
|
||||||
// b22 (account 2, outbox) has no messages.
|
|
||||||
|
|
||||||
// bt (account 2, trash): 3 messages
|
|
||||||
Message mt1 = createMessage(mMockContext, b2t, true, false, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message mt2 = createMessage(mMockContext, b2t, true, true, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
Message mt3 = createMessage(mMockContext, b2t, false, false, Message.FLAG_LOADED_COMPLETE);
|
|
||||||
|
|
||||||
assertEquals(4, getMessageCount(WidgetView.ALL_INBOX));
|
|
||||||
assertEquals(2, getUnreadCount(WidgetView.ALL_INBOX));
|
|
||||||
|
|
||||||
assertEquals(3, getMessageCount(WidgetView.ALL_STARRED));
|
|
||||||
assertEquals(1, getUnreadCount(WidgetView.ALL_STARRED));
|
|
||||||
|
|
||||||
assertEquals(2, getMessageCount(WidgetView.ALL_UNREAD));
|
|
||||||
assertEquals(2, getUnreadCount(WidgetView.ALL_UNREAD));
|
|
||||||
|
|
||||||
final WidgetView account1View = WidgetView.ALL_INBOX.getNext(mMockContext);
|
|
||||||
assertEquals(Long.toString(a1.mId), account1View.getSelectionArgs()[0]);
|
|
||||||
assertEquals(1, getMessageCount(account1View));
|
|
||||||
assertEquals(1, getUnreadCount(account1View));
|
|
||||||
|
|
||||||
final WidgetView account2View = account1View.getNext(mMockContext);
|
|
||||||
assertEquals(Long.toString(a2.mId), account2View.getSelectionArgs()[0]);
|
|
||||||
assertEquals(3, getMessageCount(account2View));
|
|
||||||
assertEquals(1, getUnreadCount(account2View));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue