19879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira/* 29879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * Copyright (C) 2012 Google Inc. 39879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * Licensed to The Android Open Source Project. 49879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * 59879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 69879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * you may not use this file except in compliance with the License. 79879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * You may obtain a copy of the License at 89879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * 99879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 109879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * 119879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * Unless required by applicable law or agreed to in writing, software 129879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 139879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * See the License for the specific language governing permissions and 159879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira * limitations under the License. 169879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira */ 179879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 189879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereirapackage com.android.mail.ui; 199879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 209879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.animation.Animator; 21370f868c834861e7732faaa9bdd07a0fa0105596Andy Huangimport android.animation.Animator.AnimatorListener; 22370f868c834861e7732faaa9bdd07a0fa0105596Andy Huangimport android.animation.AnimatorListenerAdapter; 23067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereiraimport android.animation.AnimatorSet; 249879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.animation.ObjectAnimator; 259879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.content.Context; 2637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwalimport android.content.res.Resources; 279879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.database.Cursor; 28d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereiraimport android.os.Bundle; 296a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport android.os.Handler; 30d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedyimport android.os.Looper; 311801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sappersteinimport android.support.v4.text.BidiFormatter; 327c8325de829ca029ce4547e4f0fa266124301367Scott Kennedyimport android.util.SparseArray; 336c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereiraimport android.view.LayoutInflater; 349879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.view.View; 359879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.view.ViewGroup; 369879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport android.widget.SimpleCursorAdapter; 379879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 382b806edc62eb8e83c77edc471fda4652281a15c4James Lemieuximport com.android.bitmap.BitmapCache; 396c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereiraimport com.android.mail.R; 40042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huangimport com.android.mail.analytics.Analytics; 41a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Weiimport com.android.mail.bitmap.ContactResolver; 429879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.browse.ConversationCursor; 439879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.browse.ConversationItemView; 441aba32575a08da6cbad80af8446201d73c59783dMark Weiimport com.android.mail.browse.ConversationItemViewCoordinates.CoordinatesCache; 451ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereiraimport com.android.mail.browse.SwipeableConversationItemView; 469879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.providers.Account; 477c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwalimport com.android.mail.providers.AccountObserver; 489879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.providers.Conversation; 494584a0d83e160444f931cb565185a2eea39b1683Mindy Pereiraimport com.android.mail.providers.Folder; 509879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.providers.UIProvider; 51642731419abb9037a729114d32d6ddd15af0a406Alice Yangimport com.android.mail.providers.UIProvider.ConversationListIcon; 529365a826b46b0e274df88e92534f7d871eef2aa2mindypimport com.android.mail.ui.SwipeableListView.ListItemsRemovedListener; 53b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 542ae81266ced36f2733ceab5a09c17ec939b9a62aVikram Aggarwalimport com.android.mail.utils.LogUtils; 55f82d6e7342e277f123a04fc82cc841b180655c15Andy Huangimport com.android.mail.utils.Utils; 56eb145d45c17b08ce09131e84b96350925b3db81aJin Caoimport com.google.common.collect.Lists; 576a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport com.google.common.collect.Maps; 582596f0011dcb4e86b01fc8a6362b5ac922239571Marc Blank 599879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport java.util.ArrayList; 60fac92d71ad83a34eb200cd9bcb773642e5e58de2Mindy Pereiraimport java.util.Collection; 61067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereiraimport java.util.HashMap; 629879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport java.util.HashSet; 636a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport java.util.Iterator; 647c8325de829ca029ce4547e4f0fa266124301367Scott Kennedyimport java.util.List; 656a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport java.util.Map.Entry; 669879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 67370f868c834861e7732faaa9bdd07a0fa0105596Andy Huangpublic class AnimatedAdapter extends SimpleCursorAdapter { 68a44babdac4e070034f35d984d06c675af8fee81fmindyp private static int sDismissAllShortDelay = -1; 69a44babdac4e070034f35d984d06c675af8fee81fmindyp private static int sDismissAllLongDelay = -1; 7079e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira private static final String LAST_DELETING_ITEMS = "last_deleting_items"; 716a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private static final String LEAVE_BEHIND_ITEM_DATA = "leave_behind_item_data"; 726a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private static final String LEAVE_BEHIND_ITEM_ID = "leave_behind_item_id"; 73b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal private final static int TYPE_VIEW_CONVERSATION = 0; 749365a826b46b0e274df88e92534f7d871eef2aa2mindyp private final static int TYPE_VIEW_FOOTER = 1; 75eb145d45c17b08ce09131e84b96350925b3db81aJin Cao private final static int TYPE_VIEW_HEADER = 2; 76d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp private final static int TYPE_VIEW_DONT_RECYCLE = -1; 77e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mDeletingItems = new HashSet<Long>(); 78e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final ArrayList<Long> mLastDeletingItems = new ArrayList<Long>(); 79e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mUndoingItems = new HashSet<Long>(); 80e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mSwipeDeletingItems = new HashSet<Long>(); 81e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mSwipeUndoingItems = new HashSet<Long>(); 82067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private final HashMap<Long, SwipeableConversationItemView> mAnimatingViews = 83067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira new HashMap<Long, SwipeableConversationItemView>(); 841e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira private final HashMap<Long, LeaveBehindItem> mFadeLeaveBehindItems = 858f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira new HashMap<Long, LeaveBehindItem>(); 8633519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal /** The current account */ 877c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private Account mAccount; 8833519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal private final Context mContext; 8933519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal private final ConversationSelectionSet mBatchConversations; 906a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private Runnable mCountDown; 912102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final Handler mHandler; 926a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp protected long mLastLeaveBehind = -1; 936a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp 94370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang private final AnimatorListener mAnimatorListener = new AnimatorListenerAdapter() { 95370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 96370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang @Override 97370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public void onAnimationStart(Animator animation) { 98370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (!mUndoingItems.isEmpty()) { 99370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mDeletingItems.clear(); 100370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mLastDeletingItems.clear(); 101370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mSwipeDeletingItems.clear(); 102370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 103370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 104370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 105370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang @Override 106370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public void onAnimationEnd(Animator animation) { 107370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang Object obj; 108370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (animation instanceof AnimatorSet) { 109370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang AnimatorSet set = (AnimatorSet) animation; 110370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang obj = ((ObjectAnimator) set.getChildAnimations().get(0)).getTarget(); 111370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } else { 112370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang obj = ((ObjectAnimator) animation).getTarget(); 113370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 114370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mSwipeDeletingItems); 115370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mDeletingItems); 116370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mSwipeUndoingItems); 117370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mUndoingItems); 118370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (hasFadeLeaveBehinds() && obj instanceof LeaveBehindItem) { 119370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang LeaveBehindItem objItem = (LeaveBehindItem) obj; 120370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang clearLeaveBehind(objItem.getConversationId()); 121370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang objItem.commit(); 122370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (!hasFadeLeaveBehinds()) { 123370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang // Cancel any existing animations on the remaining leave behind 124370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang // item and start fading in text immediately. 125370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang LeaveBehindItem item = getLastLeaveBehindItem(); 126370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (item != null) { 127370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang boolean cancelled = item.cancelFadeInTextAnimationIfNotStarted(); 128370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (cancelled) { 129370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang item.startFadeInTextAnimation(0 /* delay start */); 130370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 131370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 132370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 133370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang // The view types have changed, since the animating views are gone. 134370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang notifyDataSetChanged(); 135370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 136370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 137370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (!isAnimating()) { 138370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mActivity.onAnimationEnd(AnimatedAdapter.this); 139370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 140370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 141370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 142370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang }; 143370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 144c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal /** 145c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * The next action to perform. Do not read or write this. All accesses should 14637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * be in {@link #performAndSetNextAction(SwipeableListView.ListItemsRemovedListener)} which 14737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * commits the previous action, if any. 148c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal */ 1499365a826b46b0e274df88e92534f7d871eef2aa2mindyp private ListItemsRemovedListener mPendingDestruction; 15037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 151c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal /** 152c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * A destructive action that refreshes the list and performs no other action. 153c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal */ 1549365a826b46b0e274df88e92534f7d871eef2aa2mindyp private final ListItemsRemovedListener mRefreshAction = new ListItemsRemovedListener() { 155c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal @Override 1569365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void onListItemsRemoved() { 157c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal notifyDataSetChanged(); 158c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal } 159c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal }; 160c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal 161cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook public interface Listener { 162cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook void onAnimationEnd(AnimatedAdapter adapter); 163cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook } 164cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook 1656681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira private View mFooter; 1666681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira private boolean mShowFooter; 167eb145d45c17b08ce09131e84b96350925b3db81aJin Cao private List<View> mHeaders = Lists.newArrayList(); 1684584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira private Folder mFolder; 16907118a01f7183645957010779222b84930f75b4eMindy Pereira private final SwipeableListView mListView; 1707c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private boolean mSwipeEnabled; 1716a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private final HashMap<Long, LeaveBehindItem> mLeaveBehindItems = Maps.newHashMap(); 17217646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein /** True if importance markers are enabled, false otherwise. */ 17317646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein private boolean mImportanceMarkersEnabled; 17417646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein /** 17517646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein * True if chevrons (personal level indicators) should be shown: 17617646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein * an arrow ( › ) by messages sent to my address (not a mailing list), 17717646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein * and a double arrow ( » ) by messages sent only to me. 17817646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein */ 17917646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein private boolean mShowChevronsEnabled; 1802102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final ControllableActivity mActivity; 1817c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private final AccountObserver mAccountListener = new AccountObserver() { 1827c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal @Override 1837c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal public void onChanged(Account newAccount) { 184d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy if (setAccount(newAccount)) { 185d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy notifyDataSetChanged(); 186d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy } 1877c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal } 1887c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal }; 1897c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal 19037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** 19137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * A list of all views that are not conversations. These include temporary views from 1921c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy * {@link #mFleetingViews}. 19337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal */ 19437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal private final SparseArray<ConversationSpecialItemView> mSpecialViews; 1957c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 1961aba32575a08da6cbad80af8446201d73c59783dMark Wei private final CoordinatesCache mCoordinatesCache = new CoordinatesCache(); 197fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 19837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** 19937a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * Temporary views insert at specific positions relative to conversations. These can be 20037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * related to showing new features (on-boarding) or showing information about new mailboxes 20137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * that have been added by the system. 20237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal */ 20337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal private final List<ConversationSpecialItemView> mFleetingViews; 20437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 2051801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance(); 2061801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein 207d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy /** 208d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy * @return <code>true</code> if a relevant part of the account has changed, <code>false</code> 209d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy * otherwise 210d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy */ 211d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy private boolean setAccount(Account newAccount) { 212d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy final boolean accountChanged; 213d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy if (mAccount != null && mAccount.uri.equals(newAccount.uri) 21417646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein && mAccount.settings.importanceMarkersEnabled == 21517646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein newAccount.settings.importanceMarkersEnabled 216d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy && mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO) == 217d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy newAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO) 2180e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux && mAccount.settings.convListIcon == newAccount.settings.convListIcon) { 219d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy accountChanged = false; 220d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy } else { 221d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy accountChanged = true; 222d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy } 223d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy 2247c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mAccount = newAccount; 22517646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mImportanceMarkersEnabled = mAccount.settings.importanceMarkersEnabled; 22617646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mShowChevronsEnabled = mAccount.settings.showChevronsEnabled; 2277c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mSwipeEnabled = mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO); 228042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 229042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_SENDER_IMAGES_ENABLED, Boolean 230042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang .toString(newAccount.settings.convListIcon == ConversationListIcon.SENDER_IMAGE)); 2314fe0af81874976a1995191321e35c844b2229811Andy Huang Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_REPLY_ALL_SETTING, 2324fe0af81874976a1995191321e35c844b2229811Andy Huang (newAccount.settings.replyBehavior == UIProvider.DefaultReplyBehavior.REPLY) 2334fe0af81874976a1995191321e35c844b2229811Andy Huang ? "reply" 2344fe0af81874976a1995191321e35c844b2229811Andy Huang : "reply_all"); 235e6c9fb6835247d98898e2af581ad9449ad7f3184Andy Huang Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_AUTO_ADVANCE, 236e6c9fb6835247d98898e2af581ad9449ad7f3184Andy Huang UIProvider.AutoAdvance.getAutoAdvanceStr( 237e6c9fb6835247d98898e2af581ad9449ad7f3184Andy Huang newAccount.settings.getAutoAdvanceSetting())); 238d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy 239d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy return accountChanged; 2407c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal } 2417c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal 242b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 243a44babdac4e070034f35d984d06c675af8fee81fmindyp private static final int INCREASE_WAIT_COUNT = 2; 2449879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 245a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei private final BitmapCache mSendersImagesCache; 246a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei private final ContactResolver mContactResolver; 247a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 248a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal public AnimatedAdapter(Context context, ConversationCursor cursor, 249a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal ConversationSelectionSet batch, ControllableActivity activity, 2506af70772b2037d3527337f220fc053af73d4c81dScott Kennedy SwipeableListView listView, final List<ConversationSpecialItemView> specialViews) { 251a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal super(context, -1, cursor, UIProvider.CONVERSATION_PROJECTION, null, 0); 2529879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira mContext = context; 2539879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira mBatchConversations = batch; 2547c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal setAccount(mAccountListener.initialize(activity.getAccountController())); 255e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira mActivity = activity; 2566681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira mShowFooter = false; 25766bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank mListView = listView; 25837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 2598913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein mSendersImagesCache = mActivity.getSenderImageCache(); 2608913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein 2618913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein mContactResolver = 2628913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein mActivity.getContactResolver(mContext.getContentResolver(), mSendersImagesCache); 26379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 2646a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mHandler = new Handler(); 265a44babdac4e070034f35d984d06c675af8fee81fmindyp if (sDismissAllShortDelay == -1) { 26637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final Resources r = context.getResources(); 26737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal sDismissAllShortDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_short_delay); 26837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal sDismissAllLongDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_long_delay); 26937a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal } 27037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal if (specialViews != null) { 27137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mFleetingViews = new ArrayList<ConversationSpecialItemView>(specialViews); 27237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal } else { 27337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mFleetingViews = new ArrayList<ConversationSpecialItemView>(0); 2747c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 27537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** Total number of special views */ 2760e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int size = mFleetingViews.size(); 27737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mSpecialViews = new SparseArray<ConversationSpecialItemView>(size); 2787c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 2791c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Set the adapter in teaser views. 28037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView view : mFleetingViews) { 28137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal view.setAdapter(this); 28237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal } 2837c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 2847c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal } 2857c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal 2863b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp public void cancelDismissCounter() { 2874d4531a63cff536d2ee1a2929d0820981df8516amindyp cancelLeaveBehindFadeInAnimation(); 2883b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mHandler.removeCallbacks(mCountDown); 2893b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 2903b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp 2913b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp public void startDismissCounter() { 292a44babdac4e070034f35d984d06c675af8fee81fmindyp if (mLeaveBehindItems.size() > INCREASE_WAIT_COUNT) { 293a44babdac4e070034f35d984d06c675af8fee81fmindyp mHandler.postDelayed(mCountDown, sDismissAllLongDelay); 294a44babdac4e070034f35d984d06c675af8fee81fmindyp } else { 295a44babdac4e070034f35d984d06c675af8fee81fmindyp mHandler.postDelayed(mCountDown, sDismissAllShortDelay); 296a44babdac4e070034f35d984d06c675af8fee81fmindyp } 2973b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 2983b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp 2997c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal public final void destroy() { 3007c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal // Set a null cursor in the adapter 3017c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal swapCursor(null); 3027c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mAccountListener.unregisterAndDestroy(); 3036681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 3046681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira 3056681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira @Override 3066681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira public int getCount() { 30737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal // mSpecialViews only contains the views that are currently being displayed 30837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final int specialViewCount = mSpecialViews.size(); 3097c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 310eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return super.getCount() + specialViewCount + 311eb145d45c17b08ce09131e84b96350925b3db81aJin Cao (mShowFooter ? 1 : 0) + mHeaders.size(); 3129879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 3139879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 314e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu /** 315e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * Add a conversation to the undo set, but only if its deletion is still cached. If the 316e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * deletion has already been written through and the cursor doesn't have it anymore, we can't 317e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * handle it here, and should instead rely on the cursor refresh to restore the item. 318e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * @param item id for the conversation that is being undeleted. 319e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * @return true if the conversation is still cached and therefore we will handle the undo. 320e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu */ 321e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu private boolean addUndoingItem(final long item) { 322e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu if (getConversationCursor().getUnderlyingPosition(item) >= 0) { 323e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu mUndoingItems.add(item); 324e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu return true; 325e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 326e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu return false; 327e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 328e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu 3296c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira public void setUndo(boolean undo) { 3303b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (undo) { 331e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu boolean itemAdded = false; 3323b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (!mLastDeletingItems.isEmpty()) { 333e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu for (Long item : mLastDeletingItems) { 334e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu itemAdded |= addUndoingItem(item); 335e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 3363b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastDeletingItems.clear(); 3373b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3383b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (mLastLeaveBehind != -1) { 339e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu itemAdded |= addUndoingItem(mLastLeaveBehind); 3403b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastLeaveBehind = -1; 3413b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 342e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu // Start animation, only if we're handling the undo. 343e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu if (itemAdded) { 344e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu notifyDataSetChanged(); 345e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu performAndSetNextAction(mRefreshAction); 346e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 3473b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank } 3483b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank } 3493b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank 350bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira public void setSwipeUndo(boolean undo) { 3513b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (undo) { 3523b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (!mLastDeletingItems.isEmpty()) { 3533b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mSwipeUndoingItems.addAll(mLastDeletingItems); 3543b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastDeletingItems.clear(); 3553b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3563b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (mLastLeaveBehind != -1) { 3573b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mSwipeUndoingItems.add(mLastLeaveBehind); 3583b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastLeaveBehind = -1; 3593b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 360bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira // Start animation 361bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira notifyDataSetChanged(); 362bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira performAndSetNextAction(mRefreshAction); 363bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 364bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 365bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 3660abee55d48f4b7c9f2fefa59d88726ee06c2a4b9mindyp public View createConversationItemView(SwipeableConversationItemView view, Context context, 3678afccad8b03701577bb4b734a0f4fe76f6cab487Scott Kennedy Conversation conv) { 3680abee55d48f4b7c9f2fefa59d88726ee06c2a4b9mindyp if (view == null) { 36926a20758413f0f8629ea71a0943304e3ae740165Tony Mantler view = new SwipeableConversationItemView(context, mAccount.getEmailAddress()); 3709879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 371a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei view.bind(conv, mActivity, mBatchConversations, mFolder, getCheckboxSetting(), 3720e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux mSwipeEnabled, mImportanceMarkersEnabled, mShowChevronsEnabled, this); 3730abee55d48f4b7c9f2fefa59d88726ee06c2a4b9mindyp return view; 3749879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 3759879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 376dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank @Override 377dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank public boolean hasStableIds() { 378dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank return true; 379dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank } 380dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank 381dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank @Override 382dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank public int getViewTypeCount() { 383464939499eec4c4d6fd728e75598232b5948a184Mindy Pereira // TYPE_VIEW_CONVERSATION, TYPE_VIEW_DELETING, TYPE_VIEW_UNDOING, and 3846c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira // TYPE_VIEW_FOOTER, TYPE_VIEW_LEAVEBEHIND. 3856c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira return 5; 386dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank } 387dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank 388dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank @Override 389dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank public int getItemViewType(int position) { 390b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal // Try to recycle views. 391eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if (mHeaders.size() > position) { 392eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return TYPE_VIEW_HEADER; 393eb145d45c17b08ce09131e84b96350925b3db81aJin Cao } else if (mShowFooter && position == getCount() - 1) { 394e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return TYPE_VIEW_FOOTER; 395d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp } else if (hasLeaveBehinds() || isAnimating()) { 396d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // Setting as type -1 means the recycler won't take this view and 397d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // return it in get view. This is a bit of a "hammer" in that it 398d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // won't let even safe views be recycled here, 399d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // but its safer and cheaper than trying to determine individual 400d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // types. In a future release, use position/id map to try to make 401d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // this cleaner / faster to determine if the view is animating. 402d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp return TYPE_VIEW_DONT_RECYCLE; 4030e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao } else if (mSpecialViews.get(getSpecialViewsPos(position)) != null) { 4047c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy // Don't recycle the special views 4057c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy return TYPE_VIEW_DONT_RECYCLE; 406e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } 407b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal return TYPE_VIEW_CONVERSATION; 408dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank } 409dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank 41054452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal /** 411067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * Deletes the selected conversations from the conversation list view with a 412067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * translation and then a shrink. These conversations <b>must</b> have their 413067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * {@link Conversation#position} set to the position of these conversations 414067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * among the list. This will only remove the element from the list. The job 415067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * of deleting the actual element is left to the the listener. This listener 416067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * will be called when the animations are complete and is required to delete 417067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * the conversation. 418067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * @param conversations 419067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * @param listener 420067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira */ 4219365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void swipeDelete(Collection<Conversation> conversations, 4229365a826b46b0e274df88e92534f7d871eef2aa2mindyp ListItemsRemovedListener listener) { 423067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira delete(conversations, listener, mSwipeDeletingItems); 424067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 425067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 426067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 427067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira /** 428067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * Deletes the selected conversations from the conversation list view by 429067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * shrinking them away. These conversations <b>must</b> have their 430067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * {@link Conversation#position} set to the position of these conversations 431067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * among the list. This will only remove the element from the list. The job 432067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * of deleting the actual element is left to the the listener. This listener 433067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * will be called when the animations are complete and is required to delete 434067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * the conversation. 43554452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal * @param conversations 43654452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal * @param listener 43754452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal */ 4389365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void delete(Collection<Conversation> conversations, ListItemsRemovedListener listener) { 439067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira delete(conversations, listener, mDeletingItems); 440067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 441067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 4429365a826b46b0e274df88e92534f7d871eef2aa2mindyp private void delete(Collection<Conversation> conversations, ListItemsRemovedListener listener, 443e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp HashSet<Long> list) { 4443b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank // Clear out any remaining items and add the new ones 4453b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank mLastDeletingItems.clear(); 446e4abda754bad698f81f55c139a530478dae5476dPaul Westbrook // Since we are deleting new items, clear any remaining undo items 447e4abda754bad698f81f55c139a530478dae5476dPaul Westbrook mUndoingItems.clear(); 44866bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank 449b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal final int startPosition = mListView.getFirstVisiblePosition(); 450b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal final int endPosition = mListView.getLastVisiblePosition(); 45166bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank 45266bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank // Only animate visible items 453e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp for (Conversation c: conversations) { 454e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp if (c.position >= startPosition && c.position <= endPosition) { 455e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp mLastDeletingItems.add(c.id); 456e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp list.add(c.id); 45766bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } 45866bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } 45966bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank 460067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (list.isEmpty()) { 46166bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank // If we have no deleted items on screen, skip the animation 4629365a826b46b0e274df88e92534f7d871eef2aa2mindyp listener.onListItemsRemoved(); 463f01b02b09acca214892cbf865a89dbdf19f77238Scott Kennedy // If we have an action queued up, perform it 464f01b02b09acca214892cbf865a89dbdf19f77238Scott Kennedy performAndSetNextAction(null); 46566bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } else { 4669365a826b46b0e274df88e92534f7d871eef2aa2mindyp performAndSetNextAction(listener); 46766bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } 4689879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira notifyDataSetChanged(); 4699879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 4709879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 4719879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira @Override 4729879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 473eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if (mHeaders.size() > position) { 474eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return mHeaders.get(position); 475eb145d45c17b08ce09131e84b96350925b3db81aJin Cao } else if (mShowFooter && position == getCount() - 1) { 4766681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira return mFooter; 4776681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 4787c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 4797c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy // Check if this is a special view 4800e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao final ConversationSpecialItemView specialView = mSpecialViews.get( 4810e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao getSpecialViewsPos(position)); 4827c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy if (specialView != null) { 483f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy specialView.onGetView(); 484b45d1418887d8595c230788e20516bbe10c2f3eaScott Kennedy return (View) specialView; 4857c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 4867c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 487f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceBeginSection("AA.getView"); 488f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang 48937a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final ConversationCursor cursor = (ConversationCursor) getItem(position); 4901bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang final Conversation conv = cursor.getConversation(); 491983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook 492983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook // Notify the provider of this change in the position of Conversation cursor 493983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook cursor.notifyUIPositionChange(); 494983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook 495e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp if (isPositionUndoing(conv.id)) { 4966176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getUndoingView(position - getPositionOffset(position), conv, parent, 4976176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy false /* don't show swipe background */); 498e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } if (isPositionUndoingSwipe(conv.id)) { 4996176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getUndoingView(position - getPositionOffset(position), conv, parent, 5006176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy true /* show swipe background */); 501e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } else if (isPositionDeleting(conv.id)) { 5026176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getDeletingView(position - getPositionOffset(position), conv, parent, false); 503e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } else if (isPositionSwipeDeleting(conv.id)) { 5046176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getDeletingView(position - getPositionOffset(position), conv, parent, true); 5059879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 50662d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang if (hasFadeLeaveBehinds()) { 50762d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang if(isPositionFadeLeaveBehind(conv)) { 50862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang LeaveBehindItem fade = getFadeLeaveBehindItem(position, conv); 5093b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy fade.startShrinkAnimation(mAnimatorListener); 51070f0111a4337367b0cd5fcc1302b730fb332aeebMark Wei Utils.traceEndSection(); 51162d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang return fade; 51262d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 51362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 5146c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira if (hasLeaveBehinds()) { 515e358ed5c4ed1b172f5eae98f97919a8e471c98dcmindyp if (isPositionLeaveBehind(conv)) { 516370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final LeaveBehindItem fadeIn = getLeaveBehindItem(conv); 5174d4531a63cff536d2ee1a2929d0820981df8516amindyp if (conv.id == mLastLeaveBehind) { 518a44babdac4e070034f35d984d06c675af8fee81fmindyp // If it looks like the person is doing a lot of rapid 519a44babdac4e070034f35d984d06c675af8fee81fmindyp // swipes, wait patiently before animating 520a44babdac4e070034f35d984d06c675af8fee81fmindyp if (mLeaveBehindItems.size() > INCREASE_WAIT_COUNT) { 521a44babdac4e070034f35d984d06c675af8fee81fmindyp if (fadeIn.isAnimating()) { 522a44babdac4e070034f35d984d06c675af8fee81fmindyp fadeIn.increaseFadeInDelay(sDismissAllLongDelay); 523a44babdac4e070034f35d984d06c675af8fee81fmindyp } else { 524a44babdac4e070034f35d984d06c675af8fee81fmindyp fadeIn.startFadeInTextAnimation(sDismissAllLongDelay); 525a44babdac4e070034f35d984d06c675af8fee81fmindyp } 526a44babdac4e070034f35d984d06c675af8fee81fmindyp } else { 527a44babdac4e070034f35d984d06c675af8fee81fmindyp // Otherwise, assume they are just doing 1 and wait less time 528a44babdac4e070034f35d984d06c675af8fee81fmindyp fadeIn.startFadeInTextAnimation(sDismissAllShortDelay /* delay start */); 529a44babdac4e070034f35d984d06c675af8fee81fmindyp } 5304d4531a63cff536d2ee1a2929d0820981df8516amindyp } 53170f0111a4337367b0cd5fcc1302b730fb332aeebMark Wei Utils.traceEndSection(); 53284f9b5c60dc023570202859ba1d30cf9cb5e6e7aMindy Pereira return fadeIn; 5336c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5346c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5357c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 536067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (convertView != null && !(convertView instanceof SwipeableConversationItemView)) { 537067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira LogUtils.w(LOG_TAG, "Incorrect convert view received; nulling it out"); 538eb88ececd0a53c4e956240b7b619da6410e2d356mindyp convertView = newView(mContext, cursor, parent); 539c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira } else if (convertView != null) { 540c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira ((SwipeableConversationItemView) convertView).reset(); 541afd6f9246ddf645a45c8e91df5c5c2587cbf6a0dMindy Pereira } 542f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang final View v = createConversationItemView((SwipeableConversationItemView) convertView, 5438afccad8b03701577bb4b734a0f4fe76f6cab487Scott Kennedy mContext, conv); 544f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceEndSection(); 545f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang return v; 5469879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 5479879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 5486c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private boolean hasLeaveBehinds() { 5496a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp return !mLeaveBehindItems.isEmpty(); 5506c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5516c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 55262d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang private boolean hasFadeLeaveBehinds() { 5538f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira return !mFadeLeaveBehindItems.isEmpty(); 55462d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 55562d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 55679e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira public LeaveBehindItem setupLeaveBehind(Conversation target, ToastBarOperation undoOp, 557370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang int deletedRow, int viewHeight) { 5584d4531a63cff536d2ee1a2929d0820981df8516amindyp cancelLeaveBehindFadeInAnimation(); 5596a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = target.id; 56062d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang fadeOutLeaveBehindItems(); 561370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 562370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final LeaveBehindItem leaveBehind = (LeaveBehindItem) LayoutInflater.from(mContext) 563370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang .inflate(R.layout.swipe_leavebehind, mListView, false); 564370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang leaveBehind.bind(deletedRow, mAccount, this, undoOp, target, mFolder, viewHeight); 5656a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.put(target.id, leaveBehind); 566e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp mLastDeletingItems.add(target.id); 56779e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira return leaveBehind; 5686c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5696c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 5706a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp public void fadeOutSpecificLeaveBehindItem(long id) { 5716a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == id) { 5726a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = -1; 5736a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 5746a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp startFadeOutLeaveBehindItemsAnimations(); 5756a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 5766a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp 5776a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // This should kick off a timer such that there is a minimum time each item 5786a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // shows up before being dismissed. That way if the user is swiping away 5796a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // items in rapid succession, their finger position is maintained. 58062d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang public void fadeOutLeaveBehindItems() { 5816a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mCountDown == null) { 5826a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mCountDown = new Runnable() { 5836a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp @Override 5846a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp public void run() { 5856a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp startFadeOutLeaveBehindItemsAnimations(); 5866a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 5876a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp }; 5886a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } else { 5896a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mHandler.removeCallbacks(mCountDown); 5906a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 5916a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // Clear all the text since these are no longer clickable 5926a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Iterator<Entry<Long, LeaveBehindItem>> i = mLeaveBehindItems.entrySet().iterator(); 5936a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp LeaveBehindItem item; 5946a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp while (i.hasNext()) { 5956a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item = i.next().getValue(); 5966a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Conversation conv = item.getData(); 5976a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == -1 || conv.id != mLastLeaveBehind) { 598a44babdac4e070034f35d984d06c675af8fee81fmindyp item.cancelFadeInTextAnimation(); 5996a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.makeInert(); 6006a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6016a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6023b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp startDismissCounter(); 6036a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6046a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp 6056a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp protected void startFadeOutLeaveBehindItemsAnimations() { 60662d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang final int startPosition = mListView.getFirstVisiblePosition(); 60762d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang final int endPosition = mListView.getLastVisiblePosition(); 60862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 60979e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira if (hasLeaveBehinds()) { 61079e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira // If the item is visible, fade it out. Otherwise, just remove 61179e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira // it. 6126a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Iterator<Entry<Long, LeaveBehindItem>> i = mLeaveBehindItems.entrySet().iterator(); 6136a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp LeaveBehindItem item; 6146a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp while (i.hasNext()) { 6156a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item = i.next().getValue(); 6166a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Conversation conv = item.getData(); 6176a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == -1 || conv.id != mLastLeaveBehind) { 6186a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (conv.position >= startPosition && conv.position <= endPosition) { 6196a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mFadeLeaveBehindItems.put(conv.id, item); 6206a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } else { 6216a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.commit(); 6226a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6236a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp i.remove(); 6246a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 62562d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 6264d4531a63cff536d2ee1a2929d0820981df8516amindyp cancelLeaveBehindFadeInAnimation(); 62762d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 62862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang if (!mLastDeletingItems.isEmpty()) { 62962d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang mLastDeletingItems.clear(); 63062d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 63162d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang notifyDataSetChanged(); 63262d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 63362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 6344d4531a63cff536d2ee1a2929d0820981df8516amindyp private void cancelLeaveBehindFadeInAnimation() { 6354d4531a63cff536d2ee1a2929d0820981df8516amindyp LeaveBehindItem leaveBehind = getLastLeaveBehindItem(); 6364d4531a63cff536d2ee1a2929d0820981df8516amindyp if (leaveBehind != null) { 6374d4531a63cff536d2ee1a2929d0820981df8516amindyp leaveBehind.cancelFadeInTextAnimation(); 6384d4531a63cff536d2ee1a2929d0820981df8516amindyp } 6394d4531a63cff536d2ee1a2929d0820981df8516amindyp } 6404d4531a63cff536d2ee1a2929d0820981df8516amindyp 6411aba32575a08da6cbad80af8446201d73c59783dMark Wei public CoordinatesCache getCoordinatesCache() { 642fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang return mCoordinatesCache; 643fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 644fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 6451801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein public BidiFormatter getBidiFormatter() { 6461801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein return mBidiFormatter; 6471801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein } 6481801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein 6495254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp public SwipeableListView getListView() { 6505254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp return mListView; 6515254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 6525254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp 653c6adce3cf6887c4c6dd5005724565702751843d0mindyp public void commitLeaveBehindItems(boolean animate) { 654dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira // Remove any previously existing leave behinds. 6555254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp boolean changed = false; 65679e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira if (hasLeaveBehinds()) { 6576a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp for (LeaveBehindItem item : mLeaveBehindItems.values()) { 6586a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (animate) { 659dcb26aea2b27b585c35c422c870e849b8c4e41d6mindyp mFadeLeaveBehindItems.put(item.getConversationId(), item); 6606a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } else { 6616a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.commit(); 6626a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 663c6adce3cf6887c4c6dd5005724565702751843d0mindyp } 6645254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp changed = true; 6656a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = -1; 6666a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.clear(); 667dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira } 668aa55bc9cb210a46a950874f368baa07f041a4302mindyp if (hasFadeLeaveBehinds() && !animate) { 669aa55bc9cb210a46a950874f368baa07f041a4302mindyp // Find any fading leave behind items and commit them all, too. 670aa55bc9cb210a46a950874f368baa07f041a4302mindyp for (LeaveBehindItem item : mFadeLeaveBehindItems.values()) { 671aa55bc9cb210a46a950874f368baa07f041a4302mindyp item.commit(); 672aa55bc9cb210a46a950874f368baa07f041a4302mindyp } 673aa55bc9cb210a46a950874f368baa07f041a4302mindyp mFadeLeaveBehindItems.clear(); 674aa55bc9cb210a46a950874f368baa07f041a4302mindyp changed = true; 675aa55bc9cb210a46a950874f368baa07f041a4302mindyp } 67606b623852cdacc749d67d9c1b7c478dd52780297Mindy Pereira if (!mLastDeletingItems.isEmpty()) { 67706b623852cdacc749d67d9c1b7c478dd52780297Mindy Pereira mLastDeletingItems.clear(); 6785254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp changed = true; 6795254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 680fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy 681fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy for (final ConversationSpecialItemView view : mFleetingViews) { 682fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy if (view.commitLeaveBehindItem()) { 683fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy changed = true; 684fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy } 685fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy } 686fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy 6875254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp if (changed) { 6885254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp notifyDataSetChanged(); 68906b623852cdacc749d67d9c1b7c478dd52780297Mindy Pereira } 690dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira } 691dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira 69279e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira private LeaveBehindItem getLeaveBehindItem(Conversation target) { 6936a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp return mLeaveBehindItems.get(target.id); 6946c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 6956c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 69662d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang private LeaveBehindItem getFadeLeaveBehindItem(int position, Conversation target) { 6978f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira return mFadeLeaveBehindItems.get(target.id); 69862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 69962d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 700d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira @Override 701d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira public long getItemId(int position) { 702eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if ((mHeaders.size() > position) || (mShowFooter && position == getCount() - 1)) { 703d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira return -1; 704d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 705f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy 7060e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao final ConversationSpecialItemView specialView = mSpecialViews.get( 7070e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao getSpecialViewsPos(position)); 708f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy if (specialView != null) { 709f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy // TODO(skennedy) We probably want something better than this 710f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy return specialView.hashCode(); 711f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy } 712f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy 71355e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang final int cursorPos = position - getPositionOffset(position); 714348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // advance the cursor to the right position and read the cached conversation, if present 715348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // 716348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // (no need to have CursorAdapter check mDataValid because in our incarnation without 717348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // FLAG_REGISTER_CONTENT_OBSERVER, mDataValid is effectively identical to mCursor being 718348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // non-null) 719348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang final ConversationCursor cursor = getConversationCursor(); 720348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang if (cursor != null && cursor.moveToPosition(cursorPos)) { 7216cf45c601317d4b65ffb1896760fa1cb8a2b807cAndy Huang final Conversation conv = cursor.getCachedConversation(); 72255e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang if (conv != null) { 72355e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang return conv.id; 72455e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang } 72555e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang } 72655e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang return super.getItemId(cursorPos); 727d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 728d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira 7296176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy /** 7306176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy * @param position The position in the cursor 7316176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy */ 732e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private View getDeletingView(int position, Conversation conversation, ViewGroup parent, 733e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp boolean swipe) { 734c7d201d79974fd0f1e935880d51fe516f78207a2Vikram Aggarwal conversation.position = position; 735067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira SwipeableConversationItemView deletingView = mAnimatingViews.get(conversation.id); 736067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (deletingView == null) { 737067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // The undo animation consists of fading in the conversation that 738067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // had been destroyed. 739067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira deletingView = newConversationItemView(position, parent, conversation); 740370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang deletingView.startDeleteAnimation(mAnimatorListener, swipe); 741067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 742067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return deletingView; 743a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira } 744a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira 7456176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy /** 7466176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy * @param position The position in the cursor 7476176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy */ 748e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private View getUndoingView(int position, Conversation conv, ViewGroup parent, boolean swipe) { 749e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp conv.position = position; 750e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp SwipeableConversationItemView undoView = mAnimatingViews.get(conv.id); 751067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (undoView == null) { 752067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // The undo animation consists of fading in the conversation that 753067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // had been destroyed. 754e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp undoView = newConversationItemView(position, parent, conv); 755370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang undoView.startUndoAnimation(mAnimatorListener, swipe); 756067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 757067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return undoView; 758067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 759067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 7605ceab3bd6892b85b0252b987b67b70ec5055587fmindyp @Override 7615ceab3bd6892b85b0252b987b67b70ec5055587fmindyp public View newView(Context context, Cursor cursor, ViewGroup parent) { 76226a20758413f0f8629ea71a0943304e3ae740165Tony Mantler return new SwipeableConversationItemView(context, mAccount.getEmailAddress()); 7635ceab3bd6892b85b0252b987b67b70ec5055587fmindyp } 7645ceab3bd6892b85b0252b987b67b70ec5055587fmindyp 7655ceab3bd6892b85b0252b987b67b70ec5055587fmindyp @Override 7665ceab3bd6892b85b0252b987b67b70ec5055587fmindyp public void bindView(View view, Context context, Cursor cursor) { 76707fe8df87bde8732398434e55cce366a8528c181Andy Huang // no-op. we only get here from newConversationItemView(), which will immediately bind 76807fe8df87bde8732398434e55cce366a8528c181Andy Huang // on its own. 7695ceab3bd6892b85b0252b987b67b70ec5055587fmindyp } 7705ceab3bd6892b85b0252b987b67b70ec5055587fmindyp 771067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private SwipeableConversationItemView newConversationItemView(int position, ViewGroup parent, 772067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira Conversation conversation) { 773067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira SwipeableConversationItemView view = (SwipeableConversationItemView) super.getView( 774067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira position, null, parent); 775dc0617f3478b21dd3324ab10b8c433517ae95460mindyp view.reset(); 776a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei view.bind(conversation, mActivity, mBatchConversations, mFolder, getCheckboxSetting(), 7770e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux mSwipeEnabled, mImportanceMarkersEnabled, mShowChevronsEnabled, this); 778067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira mAnimatingViews.put(conversation.id, view); 779067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return view; 7809879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 7819879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 782642731419abb9037a729114d32d6ddd15af0a406Alice Yang private int getCheckboxSetting() { 783642731419abb9037a729114d32d6ddd15af0a406Alice Yang return mAccount != null ? mAccount.settings.convListIcon : 784642731419abb9037a729114d32d6ddd15af0a406Alice Yang ConversationListIcon.DEFAULT; 785642731419abb9037a729114d32d6ddd15af0a406Alice Yang } 786642731419abb9037a729114d32d6ddd15af0a406Alice Yang 787d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira @Override 788d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira public Object getItem(int position) { 7890e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao final ConversationSpecialItemView specialView = mSpecialViews.get( 7900e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao getSpecialViewsPos(position)); 791eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if (mHeaders.size() > position) { 792eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return mHeaders.get(position); 793eb145d45c17b08ce09131e84b96350925b3db81aJin Cao } else if (mShowFooter && position == getCount() - 1) { 794d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira return mFooter; 7950e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao } else if (specialView != null) { 7960e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao return specialView; 797d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 7987c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy return super.getItem(position - getPositionOffset(position)); 799d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 800d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira 801e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionDeleting(long id) { 802e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mDeletingItems.contains(id); 803a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira } 804a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira 805e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionSwipeDeleting(long id) { 806e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mSwipeDeletingItems.contains(id); 807067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 808067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 809e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionUndoing(long id) { 810e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mUndoingItems.contains(id); 8119879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 8129879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 813e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionUndoingSwipe(long id) { 814e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mSwipeUndoingItems.contains(id); 815bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 816bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 8176c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private boolean isPositionLeaveBehind(Conversation conv) { 81879e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira return hasLeaveBehinds() 8196a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp && mLeaveBehindItems.containsKey(conv.id) 82079e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira && conv.isMostlyDead(); 8216c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 8226c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 82362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang private boolean isPositionFadeLeaveBehind(Conversation conv) { 82479e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira return hasFadeLeaveBehinds() 8258f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira && mFadeLeaveBehindItems.containsKey(conv.id) 82679e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira && conv.isMostlyDead(); 82762d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 82862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 829c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal /** 830c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * Performs the pending destruction, if any and assigns the next pending action. 831c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * @param next The next action that is to be performed, possibly null (if no next action is 832c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * needed). 833c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal */ 83437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal private void performAndSetNextAction(ListItemsRemovedListener next) { 835c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal if (mPendingDestruction != null) { 8369365a826b46b0e274df88e92534f7d871eef2aa2mindyp mPendingDestruction.onListItemsRemoved(); 837c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal } 838c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal mPendingDestruction = next; 839c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal } 840c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal 841e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private void updateAnimatingConversationItems(Object obj, HashSet<Long> items) { 842067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (!items.isEmpty()) { 843067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (obj instanceof ConversationItemView) { 844067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira final ConversationItemView target = (ConversationItemView) obj; 845e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp final long id = target.getConversation().id; 846e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp items.remove(id); 847e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp mAnimatingViews.remove(id); 848067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (items.isEmpty()) { 849bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira performAndSetNextAction(null); 850067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira notifyDataSetChanged(); 851bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 852866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 8539879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 854bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 855bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 8569879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira @Override 857866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public boolean areAllItemsEnabled() { 85837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal // The animating items and some special views are not enabled. 859866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return false; 860866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 861866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 862866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira @Override 863b90db28aac1311f0ed32a786594e17c007550853Scott Kennedy public boolean isEnabled(final int position) { 86437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final ConversationSpecialItemView view = mSpecialViews.get(position); 86537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal if (view != null) { 86637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final boolean enabled = view.acceptsUserTaps(); 86737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal LogUtils.d(LOG_TAG, "AA.isEnabled(%d) = %b", position, enabled); 86837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal return enabled; 869b90db28aac1311f0ed32a786594e17c007550853Scott Kennedy } 870a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira return !isPositionDeleting(position) && !isPositionUndoing(position); 871866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 872866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 873573b9e698852c6cf2cbf0f93bc01b7abb8b64ce1Paul Westbrook public void setFooterVisibility(boolean show) { 874573b9e698852c6cf2cbf0f93bc01b7abb8b64ce1Paul Westbrook if (mShowFooter != show) { 875573b9e698852c6cf2cbf0f93bc01b7abb8b64ce1Paul Westbrook mShowFooter = show; 8766681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira notifyDataSetChanged(); 8776681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 8786681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 8796681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira 8806681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira public void addFooter(View footerView) { 8816681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira mFooter = footerView; 8826681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 8834584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira 884eb145d45c17b08ce09131e84b96350925b3db81aJin Cao public void addHeader(View headerView) { 885eb145d45c17b08ce09131e84b96350925b3db81aJin Cao mHeaders.add(headerView); 886eb145d45c17b08ce09131e84b96350925b3db81aJin Cao } 887eb145d45c17b08ce09131e84b96350925b3db81aJin Cao 8884584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira public void setFolder(Folder folder) { 8894584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira mFolder = folder; 8904584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira } 8916c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 89279e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira public void clearLeaveBehind(long itemId) { 8936a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (hasLeaveBehinds() && mLeaveBehindItems.containsKey(itemId)) { 8946a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.remove(itemId); 8958f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira } else if (hasFadeLeaveBehinds()) { 8968f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira mFadeLeaveBehindItems.remove(itemId); 89779e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } else { 89879e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira LogUtils.d(LOG_TAG, "Trying to clear a non-existant leave behind"); 89979e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } 9006a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == itemId) { 9016a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = -1; 9026a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 9036c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 9047d81600cbce3cfd366cbff9ecd1b7317ff957221Vikram Aggarwal 905d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira public void onSaveInstanceState(Bundle outState) { 906e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp long[] lastDeleting = new long[mLastDeletingItems.size()]; 90779e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira for (int i = 0; i < lastDeleting.length; i++) { 908d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira lastDeleting[i] = mLastDeletingItems.get(i); 909d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 910e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp outState.putLongArray(LAST_DELETING_ITEMS, lastDeleting); 91179e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira if (hasLeaveBehinds()) { 9126a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind != -1) { 9136a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp outState.putParcelable(LEAVE_BEHIND_ITEM_DATA, 9146a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.get(mLastLeaveBehind).getLeaveBehindData()); 9156a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp outState.putLong(LEAVE_BEHIND_ITEM_ID, mLastLeaveBehind); 9166a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 9176a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp for (LeaveBehindItem item : mLeaveBehindItems.values()) { 9186a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == -1 || item.getData().id != mLastLeaveBehind) { 9196a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.commit(); 9206a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 9216a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 92279e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } 923d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 924d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira 925d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira public void onRestoreInstanceState(Bundle outState) { 926b8ef4ac43f3570245ec476e2ee9f8a9d1d3ff36cPaul Westbrook if (outState.containsKey(LAST_DELETING_ITEMS)) { 927e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp final long[] lastDeleting = outState.getLongArray(LAST_DELETING_ITEMS); 92837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final long aLastDeleting : lastDeleting) { 92937a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mLastDeletingItems.add(aLastDeleting); 930b8ef4ac43f3570245ec476e2ee9f8a9d1d3ff36cPaul Westbrook } 931d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 9326a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (outState.containsKey(LEAVE_BEHIND_ITEM_DATA)) { 9336a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp LeaveBehindData left = 9346a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp (LeaveBehindData) outState.getParcelable(LEAVE_BEHIND_ITEM_DATA); 9356a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.put(outState.getLong(LEAVE_BEHIND_ITEM_ID), 936370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang setupLeaveBehind(left.data, left.op, left.data.position, left.height)); 93779e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } 938d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 93969e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira 94069e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira /** 94169e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira * Return if the adapter is in the process of animating anything. 94269e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira */ 94369e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira public boolean isAnimating() { 94469e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira return !mUndoingItems.isEmpty() 94569e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira || !mSwipeUndoingItems.isEmpty() 9461e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira || hasFadeLeaveBehinds() 94769e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira || !mDeletingItems.isEmpty() 94869e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira || !mSwipeDeletingItems.isEmpty(); 94969e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira } 950215d2a465dd17139d4c8cce426ae8c8ff556746emindyp 951f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang /** 952f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang * Forcibly clear any internal state that would cause {@link #isAnimating()} to return true. 953f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang * Call this in times of desperation, when you really, really want to trash state and just 954f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang * start over. 955f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang */ 956f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang public void clearAnimationState() { 957f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang if (!isAnimating()) { 958f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang return; 959f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang } 960f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang 961f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mUndoingItems.clear(); 962f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mSwipeUndoingItems.clear(); 963f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mFadeLeaveBehindItems.clear(); 964f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mDeletingItems.clear(); 965f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mSwipeDeletingItems.clear(); 966f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mAnimatingViews.clear(); 967f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang LogUtils.w(LOG_TAG, "AA.clearAnimationState forcibly cleared state, this=%s", this); 968f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang } 969f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang 970c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang @Override 971c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang public String toString() { 972c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang final StringBuilder sb = new StringBuilder("{"); 973c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(super.toString()); 974c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mUndoingItems="); 975c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mUndoingItems); 976c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mSwipeUndoingItems="); 977c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mSwipeUndoingItems); 978c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mDeletingItems="); 979c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mDeletingItems); 980c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mSwipeDeletingItems="); 981c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mSwipeDeletingItems); 982c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mLeaveBehindItems="); 983c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mLeaveBehindItems); 984c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mFadeLeaveBehindItems="); 985c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mFadeLeaveBehindItems); 986c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mLastDeletingItems="); 987c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mLastDeletingItems); 988f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(" mAnimatingViews="); 989f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(mAnimatingViews); 990f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(" mPendingDestruction="); 991f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(mPendingDestruction); 992c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append("}"); 993c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang return sb.toString(); 994c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang } 995c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang 996215d2a465dd17139d4c8cce426ae8c8ff556746emindyp /** 997215d2a465dd17139d4c8cce426ae8c8ff556746emindyp * Get the ConversationCursor associated with this adapter. 998215d2a465dd17139d4c8cce426ae8c8ff556746emindyp */ 999215d2a465dd17139d4c8cce426ae8c8ff556746emindyp public ConversationCursor getConversationCursor() { 1000215d2a465dd17139d4c8cce426ae8c8ff556746emindyp return (ConversationCursor) getCursor(); 1001215d2a465dd17139d4c8cce426ae8c8ff556746emindyp } 10027af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp 10034d4531a63cff536d2ee1a2929d0820981df8516amindyp /** 10044d4531a63cff536d2ee1a2929d0820981df8516amindyp * Get the currently visible leave behind item. 10054d4531a63cff536d2ee1a2929d0820981df8516amindyp */ 10067af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp public LeaveBehindItem getLastLeaveBehindItem() { 10077af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp if (mLastLeaveBehind != -1) { 10087af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return mLeaveBehindItems.get(mLastLeaveBehind); 10097af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 10107af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return null; 10117af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 10124d4531a63cff536d2ee1a2929d0820981df8516amindyp 10134d4531a63cff536d2ee1a2929d0820981df8516amindyp /** 10144d4531a63cff536d2ee1a2929d0820981df8516amindyp * Cancel fading out the text displayed in the leave behind item currently 10154d4531a63cff536d2ee1a2929d0820981df8516amindyp * shown. 10164d4531a63cff536d2ee1a2929d0820981df8516amindyp */ 10174d4531a63cff536d2ee1a2929d0820981df8516amindyp public void cancelFadeOutLastLeaveBehindItemText() { 10184d4531a63cff536d2ee1a2929d0820981df8516amindyp LeaveBehindItem item = getLastLeaveBehindItem(); 10194d4531a63cff536d2ee1a2929d0820981df8516amindyp if (item != null) { 10204d4531a63cff536d2ee1a2929d0820981df8516amindyp item.cancelFadeOutText(); 10214d4531a63cff536d2ee1a2929d0820981df8516amindyp } 10224d4531a63cff536d2ee1a2929d0820981df8516amindyp } 10237c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 102437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** 10251c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy * Updates special (non-conversation view) when {@link #mFleetingViews} changed 102637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal */ 10277c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy private void updateSpecialViews() { 10281c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // We recreate all the special views using mFleetingViews. 102937a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mSpecialViews.clear(); 103037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 1031bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao // If the conversation cursor hasn't finished loading, hide all special views 1032bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao if (!ConversationCursor.isCursorReadyToShow(getConversationCursor())) { 1033bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao return; 1034bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao } 1035bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao 10361c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Fleeting (temporary) views specify a position, which is 0-indexed and 10371c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // has to be adjusted for the number of fleeting views above it. 103837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView specialView : mFleetingViews) { 10390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy specialView.onUpdate(mFolder, getConversationCursor()); 10407c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10417c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy if (specialView.getShouldDisplayInList()) { 10420e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // If the special view asks for position 0, it wants to be at the top. 10430e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy int position = (specialView.getPosition()); 10442102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei 10452102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei // insert the special view into the position, but if there is 10462102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei // already an item occupying that position, move that item back 10472102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei // one position, and repeat 10482102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei ConversationSpecialItemView insert = specialView; 10492102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei while (insert != null) { 105037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final ConversationSpecialItemView kickedOut = mSpecialViews.get(position); 105137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mSpecialViews.put(position, insert); 10522102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei insert = kickedOut; 10532102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei position++; 10542102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei } 10557c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10567c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10577c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10587c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 1059e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy /** 1060e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * Gets the position of the specified {@link ConversationSpecialItemView}, as determined by 1061e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * the adapter. 1062e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * 1063e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * @return The position in the list, or a negative value if it could not be found 1064e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy */ 1065e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy public int getSpecialViewPosition(final ConversationSpecialItemView view) { 1066e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy return mSpecialViews.indexOfValue(view); 1067e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy } 1068e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy 10697c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 10707c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void notifyDataSetChanged() { 1071d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy // This may be a temporary catch for a problem, or we may leave it here. 1072d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy // b/9527863 1073d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy if (Looper.getMainLooper() != Looper.myLooper()) { 1074d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy LogUtils.wtf(LOG_TAG, "notifyDataSetChanged() called off the main thread"); 1075d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy } 1076d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy 10777c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 10787c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy super.notifyDataSetChanged(); 10797c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10807c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10817c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 10827c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void changeCursor(final Cursor cursor) { 10837c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy super.changeCursor(cursor); 10847c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 10857c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10867c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10877c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 10887c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void changeCursorAndColumns(final Cursor c, final String[] from, final int[] to) { 10897c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy super.changeCursorAndColumns(c, from, to); 10907c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 10917c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10927c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10937c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 10947c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public Cursor swapCursor(final Cursor c) { 10957c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy final Cursor oldCursor = super.swapCursor(c); 10967c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 10977c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10987c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy return oldCursor; 10997c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11007c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 1101a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei public BitmapCache getSendersImagesCache() { 1102a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei return mSendersImagesCache; 110379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 110479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 1105a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei public ContactResolver getContactResolver() { 1106a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei return mContactResolver; 110765b6d180f50922a3393795203cae68a5a2f6a33dMark Wei } 110865b6d180f50922a3393795203cae68a5a2f6a33dMark Wei 11097c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy /** 11107c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy * Gets the offset for the given position in the underlying cursor, based on any special views 11117c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy * that may be above it. 11127c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy */ 11130e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao public int getPositionOffset(int position) { 1114eb145d45c17b08ce09131e84b96350925b3db81aJin Cao int viewsAbove = mHeaders.size(); 11157c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11160e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao position -= viewsAbove; 1117da8b096b6a9128dc7c7e7d4fd46d48f9a594268dMark Wei for (int i = 0, size = mSpecialViews.size(); i < size; i++) { 111818310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal final int bidPosition = mSpecialViews.keyAt(i); 111918310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal // If the view bid for a position above the cursor position, 11200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // it is above the conversation. 11210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (bidPosition <= position) { 112218310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal viewsAbove++; 11237c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11247c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11257c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 112618310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal return viewsAbove; 11277c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11287c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11290e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao /** 11300e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao * Gets the correct position for special views given the number of headers we have. 11310e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao */ 11320e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao private int getSpecialViewsPos(final int position) { 11330e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao return position - mHeaders.size(); 11340e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao } 11350e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao 11367c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void cleanup() { 11371c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Clean up teaser views. 113837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView view : mFleetingViews) { 11397c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy view.cleanup(); 11407c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11417c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 1142fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang 1143fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang public void onConversationSelected() { 11441c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Notify teaser views. 114537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView specialView : mFleetingViews) { 1146fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang specialView.onConversationSelected(); 1147fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang } 1148fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang } 11492f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein 11502f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein public void onCabModeEntered() { 1151a2f1922c41eb5a01f1972c49ab80019a72f1aa0fAndrew Sapperstein for (final ConversationSpecialItemView specialView : mFleetingViews) { 11522f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein specialView.onCabModeEntered(); 11532f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein } 11542f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein } 115579c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 1156cc139833bc5829ba70244519e9870de783c41848Scott Kennedy public void onCabModeExited() { 1157cc139833bc5829ba70244519e9870de783c41848Scott Kennedy for (final ConversationSpecialItemView specialView : mFleetingViews) { 1158cc139833bc5829ba70244519e9870de783c41848Scott Kennedy specialView.onCabModeExited(); 1159cc139833bc5829ba70244519e9870de783c41848Scott Kennedy } 1160cc139833bc5829ba70244519e9870de783c41848Scott Kennedy } 1161cc139833bc5829ba70244519e9870de783c41848Scott Kennedy 116232ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy public void onConversationListVisibilityChanged(final boolean visible) { 116332ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy for (final ConversationSpecialItemView specialView : mFleetingViews) { 116432ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy specialView.onConversationListVisibilityChanged(visible); 116532ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 116632ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 116732ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy 1168f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy public int getViewMode() { 1169f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy return mActivity.getViewMode().getMode(); 1170f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy } 117159bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy 117259bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy public boolean isInCabMode() { 117359bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy // If we have conversation in our selected set, we're in CAB mode 117459bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy return !mBatchConversations.isEmpty(); 117559bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy } 117632ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy 117732ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy public void saveSpecialItemInstanceState(final Bundle outState) { 117832ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy for (final ConversationSpecialItemView specialView : mFleetingViews) { 117932ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy specialView.saveInstanceState(outState); 118032ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 118132ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 11827ed53776a053782ca37303075c144926647ac557Paul Westbrook} 1183