Merge "If conversation list cursor is not loaded, defer mark unread until it's loaded." into jb-ub-mail-ur8
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index e736e28..1adc85d 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -59,10 +59,9 @@
import com.android.mail.R;
import com.android.mail.browse.ConfirmDialogFragment;
import com.android.mail.browse.ConversationCursor;
-import com.android.mail.browse.ConversationItemView;
+import com.android.mail.browse.ConversationCursor.ConversationOperation;
import com.android.mail.browse.ConversationItemViewModel;
import com.android.mail.browse.ConversationPagerController;
-import com.android.mail.browse.ConversationCursor.ConversationOperation;
import com.android.mail.browse.MessageCursor.ConversationMessage;
import com.android.mail.browse.SelectedConversationsActionMenu;
import com.android.mail.browse.SyncErrorDialogFragment;
@@ -206,6 +205,19 @@
}
};
+ /**
+ * Interface for actions that are deferred until after a load completes. This is for handling
+ * user actions which affect cursors (e.g. marking messages read or unread) that happen before
+ * that cursor is loaded.
+ */
+ private interface LoadFinishedCallback {
+ void onLoadFinished();
+ }
+
+ /** The deferred actions to execute when mConversationListCursor load completes. */
+ private final ArrayList<LoadFinishedCallback> mConversationListLoadFinishedCallbacks =
+ new ArrayList<LoadFinishedCallback>();
+
private RefreshTimerTask mConversationListRefreshTask;
/** Listeners that are interested in changes to the current account. */
@@ -1012,8 +1024,8 @@
}
@Override
- public void markConversationMessagesUnread(Conversation conv, Set<Uri> unreadMessageUris,
- byte[] originalConversationInfo) {
+ public void markConversationMessagesUnread(final Conversation conv,
+ final Set<Uri> unreadMessageUris, final byte[] originalConversationInfo) {
// The only caller of this method is the conversation view, from where marking unread should
// *always* take you back to list mode.
showConversation(null);
@@ -1021,12 +1033,24 @@
// locally mark conversation unread (the provider is supposed to propagate message unread
// to conversation unread)
conv.read = false;
-
if (mConversationListCursor == null) {
- LogUtils.e(LOG_TAG, "null ConversationCursor in markConversationMessagesUnread");
- return;
- }
+ LogUtils.d(LOG_TAG, "deferring markConversationMessagesUnread for id=%d", conv.id);
+ mConversationListLoadFinishedCallbacks.add(new LoadFinishedCallback() {
+ @Override
+ public void onLoadFinished() {
+ doMarkConversationMessagesUnread(conv, unreadMessageUris,
+ originalConversationInfo);
+ }
+ });
+ } else {
+ doMarkConversationMessagesUnread(conv, unreadMessageUris, originalConversationInfo);
+ }
+ }
+
+ private void doMarkConversationMessagesUnread(Conversation conv, Set<Uri> unreadMessageUris,
+ byte[] originalConversationInfo) {
+ LogUtils.d(LOG_TAG, "performing markConversationMessagesUnread for id=%d", conv.id);
// only do a granular 'mark unread' if a subset of messages are unread
final int unreadCount = (unreadMessageUris == null) ? 0 : unreadMessageUris.size();
final int numMessages = conv.getNumMessages();
@@ -1068,14 +1092,25 @@
}
@Override
- public void markConversationsRead(Collection<Conversation> targets, boolean read,
- boolean viewed) {
- // We want to show the next conversation if we are marking unread.
- markConversationsRead(targets, read, viewed, true);
+ public void markConversationsRead(final Collection<Conversation> targets, final boolean read,
+ final boolean viewed) {
+ if (mConversationListCursor == null) {
+ LogUtils.d(LOG_TAG, "deferring markConversationsRead");
+ mConversationListLoadFinishedCallbacks.add(new LoadFinishedCallback() {
+ @Override
+ public void onLoadFinished() {
+ markConversationsRead(targets, read, viewed, true);
+ }
+ });
+ } else {
+ // We want to show the next conversation if we are marking unread.
+ markConversationsRead(targets, read, viewed, true);
+ }
}
private void markConversationsRead(final Collection<Conversation> targets, final boolean read,
final boolean markViewed, final boolean showNext) {
+ LogUtils.d(LOG_TAG, "performing markConversationsRead");
// Auto-advance if requested and the current conversation is being marked unread
if (showNext && !read) {
final Runnable operation = new Runnable() {
@@ -1141,6 +1176,8 @@
* <p>Does nothing if outside of conversation mode.</p>
*
* @param target the set of conversations being deleted/marked unread
+ * @param operation if auto-advance setting is unset, this operation is run after the user
+ * is prompted to select a setting.
* @return <code>false</code> if we aborted because the user has not yet specified a default
* action, <code>true</code> otherwise
*/
@@ -2765,6 +2802,11 @@
mConversationListCursor.addListener(AbstractActivityController.this);
mTracker.onCursorUpdated();
mConversationListObservable.notifyChanged();
+ // Handle actions that were deferred until after the conversation list was loaded.
+ for (LoadFinishedCallback callback : mConversationListLoadFinishedCallbacks) {
+ callback.onLoadFinished();
+ }
+ mConversationListLoadFinishedCallbacks.clear();
final ConversationListFragment convList = getConversationListFragment();
if (isFragmentVisible(convList)) {
diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java
index 0c2e355..fd51d2f 100644
--- a/src/com/android/mail/ui/AbstractConversationViewFragment.java
+++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java
@@ -114,13 +114,6 @@
*/
protected ConversationViewState mViewState;
- /**
- * Handles a deferred 'mark read' operation, necessary when the conversation view has finished
- * loading before the conversation cursor. Normally null unless this situation occurs.
- * When finally able to 'mark read', this observer will also be unregistered and cleaned up.
- */
- private MarkReadObserver mMarkReadObserver;
-
private long mLoadingShownTime = -1;
private final Runnable mDelayedShow = new FragmentRunnable("mDelayedShow") {
@@ -424,11 +417,6 @@
public void onDestroyView() {
super.onDestroyView();
mAccountObserver.unregisterAndDestroy();
- if (mMarkReadObserver != null) {
- mActivity.getConversationUpdater().unregisterConversationListObserver(
- mMarkReadObserver);
- mMarkReadObserver = null;
- }
}
/**
@@ -558,16 +546,14 @@
// but we do want future re-renders to mark read (e.g. "New message from X" case)
MessageCursor cursor = getMessageCursor();
if (!mConversation.isViewed() || (cursor != null && !cursor.isConversationRead())) {
- final ConversationUpdater listController = activity.getConversationUpdater();
- // The conversation cursor may not have finished loading by now (when launched via
- // notification), so watch for when it finishes and mark it read then.
- if (listController.getConversationListCursor() == null) {
- LogUtils.i(LOG_TAG, "deferring conv mark read on open for id=%d",
- mConversation.id);
- mMarkReadObserver = new MarkReadObserver(listController);
- listController.registerConversationListObserver(mMarkReadObserver);
- } else {
- markReadOnSeen(listController);
+ // Mark the conversation viewed and read.
+ activity.getConversationUpdater().markConversationsRead(Arrays.asList(mConversation),
+ true /* read */, true /* viewed */);
+
+ // and update the Message objects in the cursor so the next time a cursor update happens
+ // with these messages marked read, we know to ignore it
+ if (cursor != null) {
+ cursor.markMessagesRead();
}
}
@@ -576,19 +562,6 @@
showAutoFitPrompt();
}
- protected void markReadOnSeen(ConversationUpdater listController) {
- // Mark the conversation viewed and read.
- listController.markConversationsRead(Arrays.asList(mConversation), true /* read */,
- true /* viewed */);
-
- // and update the Message objects in the cursor so the next time a cursor update happens
- // with these messages marked read, we know to ignore it
- MessageCursor cursor = getMessageCursor();
- if (cursor != null) {
- cursor.markMessagesRead();
- }
- }
-
protected ConversationViewState getNewViewState() {
return new ConversationViewState();
}
@@ -751,27 +724,6 @@
}
}
- private class MarkReadObserver extends DataSetObserver {
- private final ConversationUpdater mListController;
-
- private MarkReadObserver(ConversationUpdater listController) {
- mListController = listController;
- }
-
- @Override
- public void onChanged() {
- if (mListController.getConversationListCursor() == null) {
- // nothing yet, keep watching
- return;
- }
- // done loading, safe to mark read now
- mListController.unregisterConversationListObserver(this);
- mMarkReadObserver = null;
- LogUtils.i(LOG_TAG, "running deferred conv mark read on open, id=%d", mConversation.id);
- markReadOnSeen(mListController);
- }
- }
-
public abstract void onConversationUpdated(Conversation conversation);
/**