ConversationPagerAdapter.java revision 2821aeaa8c06011d67344a0232079a69bd003ef8
1632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang/* 2632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Copyright (C) 2012 Google Inc. 3632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Licensed to The Android Open Source Project. 4632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * 5632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Licensed under the Apache License, Version 2.0 (the "License"); 6632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * you may not use this file except in compliance with the License. 7632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * You may obtain a copy of the License at 8632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * 9632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * http://www.apache.org/licenses/LICENSE-2.0 10632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * 11632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Unless required by applicable law or agreed to in writing, software 12632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * distributed under the License is distributed on an "AS IS" BASIS, 13632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * See the License for the specific language governing permissions and 15632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * limitations under the License. 16632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 17632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 18632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangpackage com.android.mail.browse; 19632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 20632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.app.Fragment; 21632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.app.FragmentManager; 2222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huangimport android.content.res.Resources; 23632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.database.Cursor; 24632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.database.DataSetObserver; 25632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.os.Bundle; 26632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.os.Parcelable; 2722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huangimport android.support.v4.view.ViewPager; 28589dec902e0df9f4a624aa983db7232309d29730Scott Kennedyimport android.text.TextUtils; 29632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport android.view.ViewGroup; 30632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 3122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huangimport com.android.mail.R; 32632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Account; 33632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Conversation; 34632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.Folder; 35632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.providers.UIProvider; 36f4fce1227d8b49f45e6569f1590565f2df9e8d6emindypimport com.android.mail.ui.AbstractConversationViewFragment; 37090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huangimport com.android.mail.ui.ActivityController; 38632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.ui.ConversationViewFragment; 39351ad4e87e0b0b98df9ca88266a8a63541dc5a81Andy Huangimport com.android.mail.ui.SecureConversationViewFragment; 40632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.FragmentStatePagerAdapter2; 41b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 42632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.LogUtils; 43632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 447d64612104fd861474a09994f13768360f92041dAndy Huangpublic class ConversationPagerAdapter extends FragmentStatePagerAdapter2 457d64612104fd861474a09994f13768360f92041dAndy Huang implements ViewPager.OnPageChangeListener { 46632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 47632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final DataSetObserver mListObserver = new ListObserver(); 48090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang private final DataSetObserver mFolderObserver = new FolderObserver(); 49090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang private ActivityController mController; 50632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final Bundle mCommonFragmentArgs; 51632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private final Conversation mInitialConversation; 52b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang private final Account mAccount; 53b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang private final Folder mFolder; 54632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 55632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * In singleton mode, this adapter ignores the cursor contents and size, and acts as if the 561ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang * data set size is exactly size=1, with {@link #getDefaultConversation()} at position 0. 57632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 58632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private boolean mSingletonMode = true; 59632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 601ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang * Similar to singleton mode, but once enabled, detached mode is permanent for this adapter. 611ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang */ 621ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private boolean mDetachedMode = false; 631ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang /** 64632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Adapter methods may trigger a data set change notification in the middle of a ViewPager 65632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * update, but they are not safe to handle, so we have to ignore them. This will not ignore 66632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * pager-external updates; it's impossible to be notified of an external change during 67632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * an update. 68632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * 69632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * TODO: Queue up changes like this, if there ever are any that actually modify the data set. 70632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * Right now there are none. Such a change would have to be of the form: instantiation or 71632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * setPrimary somehow adds or removes items from the conversation cursor. Crazy! 72632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 73632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private boolean mSafeToNotify; 7422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang /** 7522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * Need to keep this around to look up pager title strings. 7622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang */ 7722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang private Resources mResources; 7822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang /** 7922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * This isn't great to create a circular dependency, but our usage of {@link #getPageTitle(int)} 8022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * requires knowing which page is the currently visible to dynamically name offscreen pages 8122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * "newer" and "older". And {@link #setPrimaryItem(ViewGroup, int, Object)} does not work well 8222ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * because it isn't updated as often as {@link ViewPager#getCurrentItem()} is. 8322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * <p> 8422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * We must be careful to null out this reference when the pager and adapter are decoupled to 8522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang * minimize dangling references. 8622ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang */ 8722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang private ViewPager mPager; 88f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private boolean mSanitizedHtml; 89632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 90589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy /** 91589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy * The URI of the detached conversation. We use this to mark new CVFs as detached if they are 92589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy * created after this is set. This is to fix b/8185448. This is not needed in UR9 due changes in 93589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy * CursorStatus.isWaitingForResults(). 94589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy */ 95589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy private String mDetachedUri = null; 96589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy 972821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang private boolean mStopListeningMode = false; 982821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 992821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang /** 1002821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * After {@link #stopListening()} is called, this contains the last-known count of this adapter. 1012821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * We keep this around and use it in lieu of the Cursor's true count until imminent destruction 1022821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * to satisfy two opposing requirements: 1032821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <ol> 1042821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <li>The ViewPager always likes to know about all dataset changes via notifyDatasetChanged. 1052821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * <li>Destructive changes during pager destruction (e.g. mode transition from conversation mode 1062821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * to list mode) must be ignored, or else ViewPager will shift focus onto a neighboring 1072821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * conversation and <b>mark it read</b>. 1082821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * </ol> 1092821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * 1102821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang */ 1112821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang private int mLastKnownCount; 1122821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 113b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 114632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 1151ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private static final String BUNDLE_DETACHED_MODE = 1161ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang ConversationPagerAdapter.class.getName() + "-detachedmode"; 1171ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 11822ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang public ConversationPagerAdapter(Resources res, FragmentManager fm, Account account, 11922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang Folder folder, Conversation initialConversation) { 120632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super(fm, false /* enableSavedStates */); 12122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang mResources = res; 122f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp mCommonFragmentArgs = AbstractConversationViewFragment.makeBasicArgs(account, folder); 123632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mInitialConversation = initialConversation; 124b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang mAccount = account; 125b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang mFolder = folder; 126f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp mSanitizedHtml = mAccount.supportsCapability 127f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp (UIProvider.AccountCapabilities.SANITIZED_HTML); 128b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang } 129b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang 130b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang public boolean matches(Account account, Folder folder) { 131b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang return mAccount != null && mFolder != null && mAccount.matches(account) 132b373e3ec0e488914635345627f5734af0f0ef76bAndy Huang && mFolder.equals(folder); 133632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 134632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 135632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setSingletonMode(boolean enabled) { 136632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (mSingletonMode != enabled) { 137632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mSingletonMode = enabled; 138632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang notifyDataSetChanged(); 139632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 140632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 141632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 142632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public boolean isSingletonMode() { 1431ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return mSingletonMode; 1441ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 1451ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 14677fb5be70d76f22a64850aa7a40f6a9553960e4emindyp public boolean isDetached() { 14777fb5be70d76f22a64850aa7a40f6a9553960e4emindyp return mDetachedMode; 14877fb5be70d76f22a64850aa7a40f6a9553960e4emindyp } 14977fb5be70d76f22a64850aa7a40f6a9553960e4emindyp 1505440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal /** 1515440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * Returns true if singleton mode or detached mode have been enabled, or if the current cursor 1525440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * is null. 1535440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * @param cursor the current conversation cursor (obtained through {@link #getCursor()}. 1545440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal * @return 1555440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal */ 1565440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal public boolean isPagingDisabled(Cursor cursor) { 1575440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal return mSingletonMode || mDetachedMode || cursor == null; 158e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang } 159e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 1604de145bb568b6963d374fa0bac199218dc494186Paul Westbrook private ConversationCursor getCursor() { 161a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal if (mDetachedMode) { 162a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // In detached mode, the pager is decoupled from the cursor. Nothing should rely on the 163a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // cursor at this point. 164a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal return null; 165a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal } 166090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (mController == null) { 167192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // Happens when someone calls setActivityController(null) on us. This is done in 168192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // ConversationPagerController.stopListening() to indicate that the Conversation View 169192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal // is going away *very* soon. 1703825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang LogUtils.i(LOG_TAG, "Pager adapter has a null controller. If the conversation view" 171192fac189e6aed434556a4e37bd3c5c29ef02f29Vikram Aggarwal + " is going away, this is fine. Otherwise, the state is inconsistent"); 1728775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return null; 173e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang } 174e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 175090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang return mController.getConversationListCursor(); 176632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 177632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 178632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 179632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public Fragment getItem(int position) { 180632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang final Conversation c; 1815440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final Cursor cursor = getCursor(); 182632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 1835440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 184632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // cursor-less adapter is a size-1 cursor that points to mInitialConversation. 185632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // sanity-check 186632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (position != 0) { 187632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "pager cursor is null and position is non-zero: %d", 188632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang position); 189632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 1901ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang c = getDefaultConversation(); 191c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal c.position = 0; 192632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } else { 193e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang if (!cursor.moveToPosition(position)) { 194632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "unable to seek to ConversationCursor pos=%d (%s)", position, 195e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang cursor); 196632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return null; 197632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 198632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // TODO: switch to something like MessageCursor or AttachmentCursor 199632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // to re-use these models 200e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang c = new Conversation(cursor); 201c7694221dfa5cec3f4ae290f2266b081b2639d80Vikram Aggarwal c.position = position; 202632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 203589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy final AbstractConversationViewFragment f = getConversationViewFragment(c); 204589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy if (TextUtils.equals(mDetachedUri, c.uri.toString())) { 205589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy f.onDetachedModeEntered(); 206589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy } 207632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.getItem, frag=%s subj=%s", f, c.subject); 208632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return f; 209632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 210632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 211f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private AbstractConversationViewFragment getConversationViewFragment(Conversation c) { 212f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (mSanitizedHtml) { 213f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return ConversationViewFragment.newInstance(mCommonFragmentArgs, c); 214f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } else { 215f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return SecureConversationViewFragment.newInstance(mCommonFragmentArgs, c); 216f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 217f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 218f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp 219632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 220632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getCount() { 2212821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mStopListeningMode) { 2222821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang return mLastKnownCount; 2232821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 2242821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 2255440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final Cursor cursor = getCursor(); 2265440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 2273825f3d2284b2b57fadcfe6a4ebd9992f3c5c7bbAndy Huang LogUtils.d(LOG_TAG, "IN CPA.getCount, returning 1 (effective singleton). cursor=%s", 2285440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal cursor); 2298775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return 1; 2308775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang } 2318775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return cursor.getCount(); 232632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 233632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 234632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 235632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getItemPosition(Object item) { 236f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (!(item instanceof AbstractConversationViewFragment)) { 237632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.wtf(LOG_TAG, "getItemPosition received unexpected item: %s", item); 238632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 239632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 240f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item; 241632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return getConversationPosition(fragment.getConversation()); 242632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 243632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 244632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 245632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setPrimaryItem(ViewGroup container, int position, Object object) { 246632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.setPrimaryItem, pos=%d, frag=%s", position, 247632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang object); 248632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.setPrimaryItem(container, position, object); 249632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 250632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 251632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 252632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public CharSequence getPageTitle(int position) { 25322ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang final String title; 25422ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang final int currentPosition = mPager.getCurrentItem(); 2555440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final Cursor cursor = getCursor(); 2565440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 25768459a7b3265da5002ff331529f12f6b408c9b03Andy Huang title = null; 25868459a7b3265da5002ff331529f12f6b408c9b03Andy Huang } else if (position == currentPosition) { 259090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang int total = getCount(); 260090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (mController != null) { 261090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang final Folder f = mController.getFolder(); 262090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang if (f != null && f.totalCount > total) { 263090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang total = f.totalCount; 264090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang } 265090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang } 266090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang title = mResources.getString(R.string.conversation_count, position + 1, total); 26722ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } else { 26868459a7b3265da5002ff331529f12f6b408c9b03Andy Huang title = mResources.getString(position < currentPosition ? 26922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang R.string.conversation_newer : R.string.conversation_older); 27022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } 27122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang return title; 272632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 273632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 274632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 275632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public Parcelable saveState() { 2761ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.saveState. this=%s", this); 2771ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Bundle state = (Bundle) super.saveState(); // superclass uses a Bundle 2781ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (state == null) { 2791ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang state = new Bundle(); 2801ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 2811ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang state.putBoolean(BUNDLE_DETACHED_MODE, mDetachedMode); 2821ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return state; 283632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 284632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 285632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 286632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void restoreState(Parcelable state, ClassLoader loader) { 2871ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.restoreState. this=%s", this); 288632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.restoreState(state, loader); 2891ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (state != null) { 2901ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Bundle b = (Bundle) state; 2911ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang b.setClassLoader(loader); 2921ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang mDetachedMode = b.getBoolean(BUNDLE_DETACHED_MODE); 2931ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 294632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 295632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 296632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 297632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void startUpdate(ViewGroup container) { 298632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mSafeToNotify = false; 299632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.startUpdate(container); 300632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 301632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 302632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 303632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void finishUpdate(ViewGroup container) { 304632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.finishUpdate(container); 305632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mSafeToNotify = true; 306632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 307632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 308632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 309632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void notifyDataSetChanged() { 310632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang if (!mSafeToNotify) { 311632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.d(LOG_TAG, "IN PagerAdapter.notifyDataSetChanged, ignoring unsafe update"); 312632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return; 313632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 3141ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 315a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // If we are in detached mode, changes to the cursor are of no interest to us, but they may 316a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal // be to parent classes. 317a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal 3181ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // when the currently visible item disappears from the dataset: 3191ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // if the new version of the currently visible item has zero messages: 3201ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // notify the list controller so it can handle this 'current conversation gone' case 3211ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // (by backing out of conversation mode) 3221ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // else 3231ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // 'detach' the conversation view from the cursor, keeping the current item as-is but 3241ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // disabling swipe (effectively the same as singleton mode) 325b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy if (mController != null && !mDetachedMode && mPager != null) { 3261ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang final Conversation currConversation = mController.getCurrentConversation(); 3271ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang final int pos = getConversationPosition(currConversation); 328631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final Cursor cursor = getCursor(); 329631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal if (pos == POSITION_NONE && cursor != null && currConversation != null) { 3301ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // enable detached mode and do no more here. the fragment itself will figure out 3311ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang // if the conversation is empty (using message list cursor) and back out if needed. 3321ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang mDetachedMode = true; 333a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal mController.setDetachedMode(); 3341ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang LogUtils.i(LOG_TAG, "CPA: current conv is gone, reverting to detached mode. c=%s", 3351ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang currConversation.uri); 33618176786f320b4d4312ad1682da057434f201c13Scott Kennedy 3370558150910ece60b2d8abf1104338e8ffbb0ea17Scott Kennedy final int currentItem = mPager.getCurrentItem(); 338b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy 339b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy final AbstractConversationViewFragment fragment = 340b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy (AbstractConversationViewFragment) getFragmentAt(currentItem); 341b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy 342b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy if (fragment != null) { 343b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy fragment.onDetachedModeEntered(); 344b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy } else { 345b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy LogUtils.e(LOG_TAG, 346b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy "CPA: notifyDataSetChanged: fragment null, current item: %d", 347b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy currentItem); 348b30604cd52a1bacf4f86626181a3224bafc96b42Scott Kennedy } 349589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy 350589dec902e0df9f4a624aa983db7232309d29730Scott Kennedy mDetachedUri = currConversation.uri.toString(); 35136280f3c2939bb2dacb4077bd528900346ff4bb9mindyp } else { 352631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal // notify unaffected fragment items of the change, so they can re-render 353631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal // (the change may have been to the labels for a single conversation, for example) 354631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final AbstractConversationViewFragment frag = (cursor == null) ? null : 35526d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp (AbstractConversationViewFragment) getFragmentAt(pos); 3569d3fd92ed6091dbd0d38799222a1cf841f1c3f29Andy Huang if (frag != null && cursor.moveToPosition(pos) && frag.isUserVisible()) { 35716982472f8431aecfdb5f32aa7a97dce9064ac22mindyp // reload what we think is in the current position. 358631abc9c544925fa9c02492382dd567b705bf6feVikram Aggarwal final Conversation conv = new Conversation(cursor); 359a825aae102a6112a0b4395eb3c5417c7b0c24262mindyp conv.position = pos; 360b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp frag.onConversationUpdated(conv); 361b2b98ba97983f225eec19dc9bc5333e6ef80ee15mindyp mController.setCurrentConversation(conv); 36216982472f8431aecfdb5f32aa7a97dce9064ac22mindyp } 3631ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3641ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3651ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 366632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.notifyDataSetChanged(); 367632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 368632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 369632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 370632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void setItemVisible(Fragment item, boolean visible) { 371632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang super.setItemVisible(item, visible); 372f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp final AbstractConversationViewFragment fragment = (AbstractConversationViewFragment) item; 373632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang fragment.setExtraUserVisibleHint(visible); 374632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 375632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 3761ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang private Conversation getDefaultConversation() { 3771ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang Conversation c = (mController != null) ? mController.getCurrentConversation() : null; 3781ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (c == null) { 3791ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang c = mInitialConversation; 3801ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3811ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang return c; 3821ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang } 3831ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang 384632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public int getConversationPosition(Conversation conv) { 3855440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal final ConversationCursor cursor = getCursor(); 3865440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (isPagingDisabled(cursor)) { 3871ee96b2b100546b5b69ad42c5bc3755a4293d1a3Andy Huang if (conv != getDefaultConversation()) { 38849e0e991fe8880852b936a0f8d7d57c5b36f2154Vikram Aggarwal LogUtils.d(LOG_TAG, "unable to find conversation in singleton mode. c=%s", conv); 389632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return POSITION_NONE; 390632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 391632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return 0; 392632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 393632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 3945440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal // cursor is guaranteed to be non-null because isPagingDisabled() above checks for null 3955440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal // cursor. 3965440bf50e6b05e1551b375f797ff4bf8ed3f39ceVikram Aggarwal if (conv == null) { 3978775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang return POSITION_NONE; 3988775ffa4b8c26965352f6ec284adba3867c651d1Andy Huang } 399e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang 400ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang int result = POSITION_NONE; 401c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook final int pos = cursor.getConversationPosition(conv.id); 402c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook if (pos >= 0) { 403c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook LogUtils.d(LOG_TAG, "pager adapter found repositioned convo '%s' at pos=%d", 404c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook conv.subject, pos); 405c8f2a3c6755b3b78af810aa73ab78487567cf074Paul Westbrook result = pos; 406ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang } 407ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang 408ca85441f810fdcdd50d285ac5f0319078050c90dAndy Huang return result; 409632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 410632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 41122ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang public void setPager(ViewPager pager) { 4127d64612104fd861474a09994f13768360f92041dAndy Huang if (mPager != null) { 4137d64612104fd861474a09994f13768360f92041dAndy Huang mPager.setOnPageChangeListener(null); 4147d64612104fd861474a09994f13768360f92041dAndy Huang } 41522ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang mPager = pager; 4167d64612104fd861474a09994f13768360f92041dAndy Huang if (mPager != null) { 4177d64612104fd861474a09994f13768360f92041dAndy Huang mPager.setOnPageChangeListener(this); 4187d64612104fd861474a09994f13768360f92041dAndy Huang } 41922ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang } 42022ecc77345c86e0515c1f3c3447502c25c8c53d2Andy Huang 421090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang public void setActivityController(ActivityController controller) { 4222821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null && !mStopListeningMode) { 423090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController.unregisterConversationListObserver(mListObserver); 424860164409d7f9e4f726ed4edb2ed77afc6873ad5Andy Huang mController.unregisterFolderObserver(mFolderObserver); 425632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 426090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController = controller; 4272821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null && !mStopListeningMode) { 428090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang mController.registerConversationListObserver(mListObserver); 429860164409d7f9e4f726ed4edb2ed77afc6873ad5Andy Huang mController.registerFolderObserver(mFolderObserver); 430632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 431e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang notifyDataSetChanged(); 432632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } else { 433e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang // We're being torn down; do not notify. 434e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang // Let the pager controller manage pager lifecycle. 435632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 436632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 437632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 4382821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang /** 4392821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang * See {@link ConversationPagerController#stopListening()}. 4402821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang */ 4412821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang public void stopListening() { 4422821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang // disable the observer, but save off the current count, in case the Pager asks for it 4432821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang // from now until imminent destruction 4442821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mStopListeningMode = true; 4452821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 4462821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang if (mController != null) { 4472821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mController.unregisterConversationListObserver(mListObserver); 4482821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mController.unregisterFolderObserver(mFolderObserver); 4492821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 4502821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang mLastKnownCount = getCount(); 4512821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang } 4522821aeaa8c06011d67344a0232079a69bd003ef8Andy Huang 4537d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4547d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 4557d64612104fd861474a09994f13768360f92041dAndy Huang // no-op 4567d64612104fd861474a09994f13768360f92041dAndy Huang } 4577d64612104fd861474a09994f13768360f92041dAndy Huang 4587d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4597d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageSelected(int position) { 46066db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal if (mController == null) { 46166db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal return; 46266db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal } 46366db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal final Cursor cursor = getCursor(); 46466db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal if (cursor == null || !cursor.moveToPosition(position)) { 46566db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal // No valid cursor or it doesn't have the position we want. Bail. 46666db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal return; 4677d64612104fd861474a09994f13768360f92041dAndy Huang } 46866db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal final Conversation c = new Conversation(cursor); 46966db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal c.position = position; 47066db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal LogUtils.d(LOG_TAG, "pager adapter setting current conv: %s", c.subject); 47166db04cd71b5096b4496bf6d9468dd2ef8dc86f9Vikram Aggarwal mController.setCurrentConversation(c); 4727d64612104fd861474a09994f13768360f92041dAndy Huang } 4737d64612104fd861474a09994f13768360f92041dAndy Huang 4747d64612104fd861474a09994f13768360f92041dAndy Huang @Override 4757d64612104fd861474a09994f13768360f92041dAndy Huang public void onPageScrollStateChanged(int state) { 4767d64612104fd861474a09994f13768360f92041dAndy Huang // no-op 4777d64612104fd861474a09994f13768360f92041dAndy Huang } 4787d64612104fd861474a09994f13768360f92041dAndy Huang 479090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang // update the pager title strip as the Folder's conversation count changes 480090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang private class FolderObserver extends DataSetObserver { 481090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang @Override 482090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang public void onChanged() { 483090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang notifyDataSetChanged(); 484090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang } 485090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang } 486090db1ec6fef366ab9e319040a00eca078ed41c3Andy Huang 487632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang // update the pager dataset as the Controller's cursor changes 488632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private class ListObserver extends DataSetObserver { 489632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 490632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void onChanged() { 491e3df1ad8e630d7d61b4d68f8328f97dd11448b5dAndy Huang notifyDataSetChanged(); 492632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 493632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang @Override 494632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public void onInvalidated() { 495632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 496632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 497632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 498632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang} 499