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; 370a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Caoimport android.widget.Space; 389879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 392b806edc62eb8e83c77edc471fda4652281a15c4James Lemieuximport com.android.bitmap.BitmapCache; 406c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereiraimport com.android.mail.R; 41042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huangimport com.android.mail.analytics.Analytics; 42a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Weiimport com.android.mail.bitmap.ContactResolver; 439879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.browse.ConversationCursor; 449879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.browse.ConversationItemView; 451aba32575a08da6cbad80af8446201d73c59783dMark Weiimport com.android.mail.browse.ConversationItemViewCoordinates.CoordinatesCache; 461ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereiraimport com.android.mail.browse.SwipeableConversationItemView; 479879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.providers.Account; 487c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwalimport com.android.mail.providers.AccountObserver; 499879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.providers.Conversation; 504584a0d83e160444f931cb565185a2eea39b1683Mindy Pereiraimport com.android.mail.providers.Folder; 519879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport com.android.mail.providers.UIProvider; 52642731419abb9037a729114d32d6ddd15af0a406Alice Yangimport com.android.mail.providers.UIProvider.ConversationListIcon; 539365a826b46b0e274df88e92534f7d871eef2aa2mindypimport com.android.mail.ui.SwipeableListView.ListItemsRemovedListener; 54b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 552ae81266ced36f2733ceab5a09c17ec939b9a62aVikram Aggarwalimport com.android.mail.utils.LogUtils; 56f82d6e7342e277f123a04fc82cc841b180655c15Andy Huangimport com.android.mail.utils.Utils; 57eb145d45c17b08ce09131e84b96350925b3db81aJin Caoimport com.google.common.collect.Lists; 586a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport com.google.common.collect.Maps; 592596f0011dcb4e86b01fc8a6362b5ac922239571Marc Blank 609879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport java.util.ArrayList; 61fac92d71ad83a34eb200cd9bcb773642e5e58de2Mindy Pereiraimport java.util.Collection; 62067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereiraimport java.util.HashMap; 639879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereiraimport java.util.HashSet; 646a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport java.util.Iterator; 657c8325de829ca029ce4547e4f0fa266124301367Scott Kennedyimport java.util.List; 666a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindypimport java.util.Map.Entry; 679879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 68370f868c834861e7732faaa9bdd07a0fa0105596Andy Huangpublic class AnimatedAdapter extends SimpleCursorAdapter { 69a44babdac4e070034f35d984d06c675af8fee81fmindyp private static int sDismissAllShortDelay = -1; 70a44babdac4e070034f35d984d06c675af8fee81fmindyp private static int sDismissAllLongDelay = -1; 7179e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira private static final String LAST_DELETING_ITEMS = "last_deleting_items"; 726a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private static final String LEAVE_BEHIND_ITEM_DATA = "leave_behind_item_data"; 736a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private static final String LEAVE_BEHIND_ITEM_ID = "leave_behind_item_id"; 74b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal private final static int TYPE_VIEW_CONVERSATION = 0; 759365a826b46b0e274df88e92534f7d871eef2aa2mindyp private final static int TYPE_VIEW_FOOTER = 1; 76eb145d45c17b08ce09131e84b96350925b3db81aJin Cao private final static int TYPE_VIEW_HEADER = 2; 77d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp private final static int TYPE_VIEW_DONT_RECYCLE = -1; 78e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mDeletingItems = new HashSet<Long>(); 79e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final ArrayList<Long> mLastDeletingItems = new ArrayList<Long>(); 80e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mUndoingItems = new HashSet<Long>(); 81e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mSwipeDeletingItems = new HashSet<Long>(); 82e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private final HashSet<Long> mSwipeUndoingItems = new HashSet<Long>(); 83067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private final HashMap<Long, SwipeableConversationItemView> mAnimatingViews = 84067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira new HashMap<Long, SwipeableConversationItemView>(); 851e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira private final HashMap<Long, LeaveBehindItem> mFadeLeaveBehindItems = 868f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira new HashMap<Long, LeaveBehindItem>(); 8733519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal /** The current account */ 887c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private Account mAccount; 8933519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal private final Context mContext; 90ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao private final ConversationCheckedSet mBatchConversations; 916a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private Runnable mCountDown; 922102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final Handler mHandler; 936a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp protected long mLastLeaveBehind = -1; 946a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp 95370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang private final AnimatorListener mAnimatorListener = new AnimatorListenerAdapter() { 96370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 97370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang @Override 98370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public void onAnimationStart(Animator animation) { 99370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (!mUndoingItems.isEmpty()) { 100370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mDeletingItems.clear(); 101370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mLastDeletingItems.clear(); 102370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mSwipeDeletingItems.clear(); 103370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 104370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 105370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 106370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang @Override 107370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public void onAnimationEnd(Animator animation) { 108370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang Object obj; 109370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (animation instanceof AnimatorSet) { 110370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang AnimatorSet set = (AnimatorSet) animation; 111370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang obj = ((ObjectAnimator) set.getChildAnimations().get(0)).getTarget(); 112370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } else { 113370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang obj = ((ObjectAnimator) animation).getTarget(); 114370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 115370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mSwipeDeletingItems); 116370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mDeletingItems); 117370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mSwipeUndoingItems); 118370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang updateAnimatingConversationItems(obj, mUndoingItems); 119370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (hasFadeLeaveBehinds() && obj instanceof LeaveBehindItem) { 120370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang LeaveBehindItem objItem = (LeaveBehindItem) obj; 121370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang clearLeaveBehind(objItem.getConversationId()); 122370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang objItem.commit(); 123370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (!hasFadeLeaveBehinds()) { 124370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang // Cancel any existing animations on the remaining leave behind 125370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang // item and start fading in text immediately. 126370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang LeaveBehindItem item = getLastLeaveBehindItem(); 127370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (item != null) { 128370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang boolean cancelled = item.cancelFadeInTextAnimationIfNotStarted(); 129370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (cancelled) { 130370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang item.startFadeInTextAnimation(0 /* delay start */); 131370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 132370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 133370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 134370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang // The view types have changed, since the animating views are gone. 135370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang notifyDataSetChanged(); 136370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 137370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 138370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang if (!isAnimating()) { 139370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mActivity.onAnimationEnd(AnimatedAdapter.this); 140370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 141370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 142370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 143370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang }; 144370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 145c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal /** 146c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * The next action to perform. Do not read or write this. All accesses should 14737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * be in {@link #performAndSetNextAction(SwipeableListView.ListItemsRemovedListener)} which 14837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * commits the previous action, if any. 149c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal */ 1509365a826b46b0e274df88e92534f7d871eef2aa2mindyp private ListItemsRemovedListener mPendingDestruction; 15137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 152c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal /** 153c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * A destructive action that refreshes the list and performs no other action. 154c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal */ 1559365a826b46b0e274df88e92534f7d871eef2aa2mindyp private final ListItemsRemovedListener mRefreshAction = new ListItemsRemovedListener() { 156c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal @Override 1579365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void onListItemsRemoved() { 158c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal notifyDataSetChanged(); 159c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal } 160c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal }; 161c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal 162cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook public interface Listener { 163cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook void onAnimationEnd(AnimatedAdapter adapter); 164cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook } 165cff1aeaff92efb9f7a03203d9f757a2820b87686Paul Westbrook 1660a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao private Space mDefaultFooter; 1676681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira private View mFooter; 1680a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao // If true, the last list item will be mFooter, otherwise it's mDefaultFooter. 1690a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao private boolean mShowCustomFooter; 170eb145d45c17b08ce09131e84b96350925b3db81aJin Cao private List<View> mHeaders = Lists.newArrayList(); 1714584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira private Folder mFolder; 17207118a01f7183645957010779222b84930f75b4eMindy Pereira private final SwipeableListView mListView; 1737c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private boolean mSwipeEnabled; 1746a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp private final HashMap<Long, LeaveBehindItem> mLeaveBehindItems = Maps.newHashMap(); 17517646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein /** True if importance markers are enabled, false otherwise. */ 17617646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein private boolean mImportanceMarkersEnabled; 17717646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein /** 17817646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein * True if chevrons (personal level indicators) should be shown: 17917646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein * an arrow ( › ) by messages sent to my address (not a mailing list), 18017646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein * and a double arrow ( » ) by messages sent only to me. 18117646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein */ 18217646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein private boolean mShowChevronsEnabled; 1832102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei private final ControllableActivity mActivity; 1847c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal private final AccountObserver mAccountListener = new AccountObserver() { 1857c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal @Override 1867c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal public void onChanged(Account newAccount) { 187d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy if (setAccount(newAccount)) { 188d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy notifyDataSetChanged(); 189d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy } 1907c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal } 1917c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal }; 1927c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal 19337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** 19437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * A list of all views that are not conversations. These include temporary views from 1951c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy * {@link #mFleetingViews}. 19637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal */ 19737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal private final SparseArray<ConversationSpecialItemView> mSpecialViews; 1987c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 1991aba32575a08da6cbad80af8446201d73c59783dMark Wei private final CoordinatesCache mCoordinatesCache = new CoordinatesCache(); 200fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 20137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** 20237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * Temporary views insert at specific positions relative to conversations. These can be 20337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * related to showing new features (on-boarding) or showing information about new mailboxes 20437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal * that have been added by the system. 20537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal */ 20637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal private final List<ConversationSpecialItemView> mFleetingViews; 20737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 2081801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance(); 2091801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein 210d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy /** 211d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy * @return <code>true</code> if a relevant part of the account has changed, <code>false</code> 212d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy * otherwise 213d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy */ 214d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy private boolean setAccount(Account newAccount) { 215d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy final boolean accountChanged; 216d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy if (mAccount != null && mAccount.uri.equals(newAccount.uri) 21717646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein && mAccount.settings.importanceMarkersEnabled == 21817646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein newAccount.settings.importanceMarkersEnabled 219d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy && mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO) == 220d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy newAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO) 2210e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux && mAccount.settings.convListIcon == newAccount.settings.convListIcon) { 222d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy accountChanged = false; 223d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy } else { 224d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy accountChanged = true; 225d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy } 226d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy 2277c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mAccount = newAccount; 22817646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mImportanceMarkersEnabled = mAccount.settings.importanceMarkersEnabled; 22917646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mShowChevronsEnabled = mAccount.settings.showChevronsEnabled; 2307c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mSwipeEnabled = mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO); 231042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 232042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_SENDER_IMAGES_ENABLED, Boolean 233042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang .toString(newAccount.settings.convListIcon == ConversationListIcon.SENDER_IMAGE)); 2344fe0af81874976a1995191321e35c844b2229811Andy Huang Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_REPLY_ALL_SETTING, 2354fe0af81874976a1995191321e35c844b2229811Andy Huang (newAccount.settings.replyBehavior == UIProvider.DefaultReplyBehavior.REPLY) 2364fe0af81874976a1995191321e35c844b2229811Andy Huang ? "reply" 2374fe0af81874976a1995191321e35c844b2229811Andy Huang : "reply_all"); 238e6c9fb6835247d98898e2af581ad9449ad7f3184Andy Huang Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_AUTO_ADVANCE, 239e6c9fb6835247d98898e2af581ad9449ad7f3184Andy Huang UIProvider.AutoAdvance.getAutoAdvanceStr( 240e6c9fb6835247d98898e2af581ad9449ad7f3184Andy Huang newAccount.settings.getAutoAdvanceSetting())); 241d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy 242d6522ea881e80ab849f2a88565db5a6a73e7623eScott Kennedy return accountChanged; 2437c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal } 2447c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal 245b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 246a44babdac4e070034f35d984d06c675af8fee81fmindyp private static final int INCREASE_WAIT_COUNT = 2; 2479879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 248a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei private final BitmapCache mSendersImagesCache; 249a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei private final ContactResolver mContactResolver; 250a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 251a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal public AnimatedAdapter(Context context, ConversationCursor cursor, 252ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao ConversationCheckedSet batch, ControllableActivity activity, 2536af70772b2037d3527337f220fc053af73d4c81dScott Kennedy SwipeableListView listView, final List<ConversationSpecialItemView> specialViews) { 254a91d00b4de3092b41af5f36436d3b49fe4586f64Vikram Aggarwal super(context, -1, cursor, UIProvider.CONVERSATION_PROJECTION, null, 0); 2559879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira mContext = context; 2569879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira mBatchConversations = batch; 2577c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal setAccount(mAccountListener.initialize(activity.getAccountController())); 258e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira mActivity = activity; 2590a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao mDefaultFooter = (Space) LayoutInflater.from(context).inflate( 2600a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao R.layout.conversation_list_default_footer, listView, false); 2610a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao mShowCustomFooter = false; 26266bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank mListView = listView; 26337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 2648913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein mSendersImagesCache = mActivity.getSenderImageCache(); 2658913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein 2668913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein mContactResolver = 2678913ca6aebe6017efe8060b61b8ad38eda95aa8bAndrew Sapperstein mActivity.getContactResolver(mContext.getContentResolver(), mSendersImagesCache); 26879c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 2696a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mHandler = new Handler(); 270a44babdac4e070034f35d984d06c675af8fee81fmindyp if (sDismissAllShortDelay == -1) { 27137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final Resources r = context.getResources(); 27237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal sDismissAllShortDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_short_delay); 27337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal sDismissAllLongDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_long_delay); 27437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal } 27537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal if (specialViews != null) { 27637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mFleetingViews = new ArrayList<ConversationSpecialItemView>(specialViews); 27737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal } else { 27837a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mFleetingViews = new ArrayList<ConversationSpecialItemView>(0); 2797c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 28037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** Total number of special views */ 2810e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int size = mFleetingViews.size(); 28237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mSpecialViews = new SparseArray<ConversationSpecialItemView>(size); 2837c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 2841c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Set the adapter in teaser views. 28537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView view : mFleetingViews) { 28637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal view.setAdapter(this); 28737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal } 2887c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 2897c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal } 2907c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal 2913b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp public void cancelDismissCounter() { 2924d4531a63cff536d2ee1a2929d0820981df8516amindyp cancelLeaveBehindFadeInAnimation(); 2933b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mHandler.removeCallbacks(mCountDown); 2943b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 2953b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp 2963b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp public void startDismissCounter() { 297a44babdac4e070034f35d984d06c675af8fee81fmindyp if (mLeaveBehindItems.size() > INCREASE_WAIT_COUNT) { 298a44babdac4e070034f35d984d06c675af8fee81fmindyp mHandler.postDelayed(mCountDown, sDismissAllLongDelay); 299a44babdac4e070034f35d984d06c675af8fee81fmindyp } else { 300a44babdac4e070034f35d984d06c675af8fee81fmindyp mHandler.postDelayed(mCountDown, sDismissAllShortDelay); 301a44babdac4e070034f35d984d06c675af8fee81fmindyp } 3023b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3033b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp 3047c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal public final void destroy() { 3057c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal // Set a null cursor in the adapter 3067c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal swapCursor(null); 3077c401b7896910c00e6234e8774aab0be45740d32Vikram Aggarwal mAccountListener.unregisterAndDestroy(); 3086681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 3096681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira 3106681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira @Override 3116681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira public int getCount() { 31237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal // mSpecialViews only contains the views that are currently being displayed 31337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final int specialViewCount = mSpecialViews.size(); 3147c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 3154d888936856ea0e9bc108aa2642ff8e21afeff44Jin Cao // Headers are not included in the content count because their availability is not affected 3164d888936856ea0e9bc108aa2642ff8e21afeff44Jin Cao // by the underlying cursor. 3174d888936856ea0e9bc108aa2642ff8e21afeff44Jin Cao // 3184d888936856ea0e9bc108aa2642ff8e21afeff44Jin Cao // !! This count still includes the teasers since they are separate from headers. !! 3198c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao int contentCount = super.getCount() + specialViewCount; 3208c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao // If we have no content, the only possible thing to show is custom footer (e.g. loading) 3218c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao if (contentCount == 0) { 3228c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao contentCount += mShowCustomFooter ? 1 : 0; 3238c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao } else { 3248c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao // Only add header & footer is always visible when there are content 3258c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao contentCount += 1 /* footer */ + mHeaders.size(); 3268c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao } 3278c0fdff583d0471bd830bb7e0c33df8beaa25e93Jin Cao return contentCount; 328ce407cd978b0482b67426706ddc972a89a507999Jin Cao } 329ce407cd978b0482b67426706ddc972a89a507999Jin Cao 330ce407cd978b0482b67426706ddc972a89a507999Jin Cao /** 331e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * Add a conversation to the undo set, but only if its deletion is still cached. If the 332e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * deletion has already been written through and the cursor doesn't have it anymore, we can't 333e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * handle it here, and should instead rely on the cursor refresh to restore the item. 334e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * @param item id for the conversation that is being undeleted. 335e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu * @return true if the conversation is still cached and therefore we will handle the undo. 336e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu */ 337e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu private boolean addUndoingItem(final long item) { 338e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu if (getConversationCursor().getUnderlyingPosition(item) >= 0) { 339e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu mUndoingItems.add(item); 340e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu return true; 341e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 342e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu return false; 343e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 344e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu 3456c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira public void setUndo(boolean undo) { 3463b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (undo) { 347e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu boolean itemAdded = false; 3483b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (!mLastDeletingItems.isEmpty()) { 349e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu for (Long item : mLastDeletingItems) { 350e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu itemAdded |= addUndoingItem(item); 351e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 3523b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastDeletingItems.clear(); 3533b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3543b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (mLastLeaveBehind != -1) { 355e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu itemAdded |= addUndoingItem(mLastLeaveBehind); 3563b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastLeaveBehind = -1; 3573b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 358e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu // Start animation, only if we're handling the undo. 359e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu if (itemAdded) { 360e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu notifyDataSetChanged(); 361e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu performAndSetNextAction(mRefreshAction); 362e5ca52d91ee8482a81abbd80d625ef592db6fa8dYu Ping Hu } 3633b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank } 3643b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank } 3653b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank 366bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira public void setSwipeUndo(boolean undo) { 3673b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (undo) { 3683b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (!mLastDeletingItems.isEmpty()) { 3693b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mSwipeUndoingItems.addAll(mLastDeletingItems); 3703b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastDeletingItems.clear(); 3713b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 3723b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp if (mLastLeaveBehind != -1) { 3733b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mSwipeUndoingItems.add(mLastLeaveBehind); 3743b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp mLastLeaveBehind = -1; 3753b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp } 376bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira // Start animation 377bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira notifyDataSetChanged(); 378bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira performAndSetNextAction(mRefreshAction); 379bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 380bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 381bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 3820abee55d48f4b7c9f2fefa59d88726ee06c2a4b9mindyp public View createConversationItemView(SwipeableConversationItemView view, Context context, 383f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao Conversation conv) { 3840abee55d48f4b7c9f2fefa59d88726ee06c2a4b9mindyp if (view == null) { 3853dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao view = new SwipeableConversationItemView(context, mAccount); 3869879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 387a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei view.bind(conv, mActivity, mBatchConversations, mFolder, getCheckboxSetting(), 388f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao mSwipeEnabled, mImportanceMarkersEnabled, mShowChevronsEnabled, this); 3890abee55d48f4b7c9f2fefa59d88726ee06c2a4b9mindyp return view; 3909879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 3919879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 392dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank @Override 393dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank public boolean hasStableIds() { 394dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank return true; 395dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank } 396dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank 397dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank @Override 398dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank public int getViewTypeCount() { 399464939499eec4c4d6fd728e75598232b5948a184Mindy Pereira // TYPE_VIEW_CONVERSATION, TYPE_VIEW_DELETING, TYPE_VIEW_UNDOING, and 4006c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira // TYPE_VIEW_FOOTER, TYPE_VIEW_LEAVEBEHIND. 4016c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira return 5; 402dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank } 403dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank 404dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank @Override 405dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank public int getItemViewType(int position) { 406b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal // Try to recycle views. 407eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if (mHeaders.size() > position) { 408eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return TYPE_VIEW_HEADER; 4090a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao } else if (position == getCount() - 1) { 410e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return TYPE_VIEW_FOOTER; 411d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp } else if (hasLeaveBehinds() || isAnimating()) { 412d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // Setting as type -1 means the recycler won't take this view and 413d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // return it in get view. This is a bit of a "hammer" in that it 414d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // won't let even safe views be recycled here, 415d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // but its safer and cheaper than trying to determine individual 416d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // types. In a future release, use position/id map to try to make 417d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp // this cleaner / faster to determine if the view is animating. 418d0f9578e0c0e01e981937310613ed0bb2550ba42mindyp return TYPE_VIEW_DONT_RECYCLE; 4190e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao } else if (mSpecialViews.get(getSpecialViewsPos(position)) != null) { 4207c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy // Don't recycle the special views 4217c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy return TYPE_VIEW_DONT_RECYCLE; 422e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } 423b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal return TYPE_VIEW_CONVERSATION; 424dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank } 425dd10bc8736282262da0cd9a5f9a0236c10b47028Marc Blank 42654452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal /** 427067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * Deletes the selected conversations from the conversation list view with a 428067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * translation and then a shrink. These conversations <b>must</b> have their 429067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * {@link Conversation#position} set to the position of these conversations 430067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * among the list. This will only remove the element from the list. The job 431067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * of deleting the actual element is left to the the listener. This listener 432067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * will be called when the animations are complete and is required to delete 433067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * the conversation. 434067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * @param conversations 435067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * @param listener 436067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira */ 4379365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void swipeDelete(Collection<Conversation> conversations, 4389365a826b46b0e274df88e92534f7d871eef2aa2mindyp ListItemsRemovedListener listener) { 439067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira delete(conversations, listener, mSwipeDeletingItems); 440067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 441067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 442067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 443067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira /** 444067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * Deletes the selected conversations from the conversation list view by 445067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * shrinking them away. These conversations <b>must</b> have their 446067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * {@link Conversation#position} set to the position of these conversations 447067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * among the list. This will only remove the element from the list. The job 448067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * of deleting the actual element is left to the the listener. This listener 449067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * will be called when the animations are complete and is required to delete 450067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * the conversation. 45154452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal * @param conversations 45254452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal * @param listener 45354452ae7a9cdb607ed1db5e74077b5ebd95c46a2Vikram Aggarwal */ 4549365a826b46b0e274df88e92534f7d871eef2aa2mindyp public void delete(Collection<Conversation> conversations, ListItemsRemovedListener listener) { 455067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira delete(conversations, listener, mDeletingItems); 456067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 457067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 4589365a826b46b0e274df88e92534f7d871eef2aa2mindyp private void delete(Collection<Conversation> conversations, ListItemsRemovedListener listener, 459e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp HashSet<Long> list) { 4603b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank // Clear out any remaining items and add the new ones 4613b2d91316fcfc407ba0e40ad35dea659922dccecMarc Blank mLastDeletingItems.clear(); 462e4abda754bad698f81f55c139a530478dae5476dPaul Westbrook // Since we are deleting new items, clear any remaining undo items 463e4abda754bad698f81f55c139a530478dae5476dPaul Westbrook mUndoingItems.clear(); 46466bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank 465b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal final int startPosition = mListView.getFirstVisiblePosition(); 466b54a46756017c81a9f253df4d4e8f967f137f803Vikram Aggarwal final int endPosition = mListView.getLastVisiblePosition(); 46766bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank 46866bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank // Only animate visible items 469e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp for (Conversation c: conversations) { 470e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp if (c.position >= startPosition && c.position <= endPosition) { 471e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp mLastDeletingItems.add(c.id); 472e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp list.add(c.id); 47366bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } 47466bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } 47566bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank 476067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (list.isEmpty()) { 47766bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank // If we have no deleted items on screen, skip the animation 4789365a826b46b0e274df88e92534f7d871eef2aa2mindyp listener.onListItemsRemoved(); 479f01b02b09acca214892cbf865a89dbdf19f77238Scott Kennedy // If we have an action queued up, perform it 480f01b02b09acca214892cbf865a89dbdf19f77238Scott Kennedy performAndSetNextAction(null); 48166bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } else { 4829365a826b46b0e274df88e92534f7d871eef2aa2mindyp performAndSetNextAction(listener); 48366bee6e884dc7f6c6f880fc0213bbd5e4c23e476Marc Blank } 4849879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira notifyDataSetChanged(); 4859879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 4869879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 4879879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira @Override 4889879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 489eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if (mHeaders.size() > position) { 490eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return mHeaders.get(position); 4910a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao } else if (position == getCount() - 1) { 4920a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao return mShowCustomFooter ? mFooter : mDefaultFooter; 4936681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 4947c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 4957c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy // Check if this is a special view 4960e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao final ConversationSpecialItemView specialView = mSpecialViews.get( 4970e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao getSpecialViewsPos(position)); 4987c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy if (specialView != null) { 499f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy specialView.onGetView(); 500b45d1418887d8595c230788e20516bbe10c2f3eaScott Kennedy return (View) specialView; 5017c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 5027c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 503f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceBeginSection("AA.getView"); 504f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang 50537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final ConversationCursor cursor = (ConversationCursor) getItem(position); 5061bca265b7a8a3f9ea08e0ae51eeb145f0883a266Andy Huang final Conversation conv = cursor.getConversation(); 507983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook 508983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook // Notify the provider of this change in the position of Conversation cursor 509983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook cursor.notifyUIPositionChange(); 510983a723931447b6261a2e42b25e6f931dba6de33Paul Westbrook 511e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp if (isPositionUndoing(conv.id)) { 5126176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getUndoingView(position - getPositionOffset(position), conv, parent, 5136176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy false /* don't show swipe background */); 514e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } if (isPositionUndoingSwipe(conv.id)) { 5156176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getUndoingView(position - getPositionOffset(position), conv, parent, 5166176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy true /* show swipe background */); 517e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } else if (isPositionDeleting(conv.id)) { 5186176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getDeletingView(position - getPositionOffset(position), conv, parent, false); 519e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp } else if (isPositionSwipeDeleting(conv.id)) { 5206176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy return getDeletingView(position - getPositionOffset(position), conv, parent, true); 5219879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 52262d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang if (hasFadeLeaveBehinds()) { 52362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang if(isPositionFadeLeaveBehind(conv)) { 52462d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang LeaveBehindItem fade = getFadeLeaveBehindItem(position, conv); 5253b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy fade.startShrinkAnimation(mAnimatorListener); 52670f0111a4337367b0cd5fcc1302b730fb332aeebMark Wei Utils.traceEndSection(); 52762d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang return fade; 52862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 52962d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 5306c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira if (hasLeaveBehinds()) { 531e358ed5c4ed1b172f5eae98f97919a8e471c98dcmindyp if (isPositionLeaveBehind(conv)) { 532370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final LeaveBehindItem fadeIn = getLeaveBehindItem(conv); 5334d4531a63cff536d2ee1a2929d0820981df8516amindyp if (conv.id == mLastLeaveBehind) { 534a44babdac4e070034f35d984d06c675af8fee81fmindyp // If it looks like the person is doing a lot of rapid 535a44babdac4e070034f35d984d06c675af8fee81fmindyp // swipes, wait patiently before animating 536a44babdac4e070034f35d984d06c675af8fee81fmindyp if (mLeaveBehindItems.size() > INCREASE_WAIT_COUNT) { 537a44babdac4e070034f35d984d06c675af8fee81fmindyp if (fadeIn.isAnimating()) { 538a44babdac4e070034f35d984d06c675af8fee81fmindyp fadeIn.increaseFadeInDelay(sDismissAllLongDelay); 539a44babdac4e070034f35d984d06c675af8fee81fmindyp } else { 540a44babdac4e070034f35d984d06c675af8fee81fmindyp fadeIn.startFadeInTextAnimation(sDismissAllLongDelay); 541a44babdac4e070034f35d984d06c675af8fee81fmindyp } 542a44babdac4e070034f35d984d06c675af8fee81fmindyp } else { 543a44babdac4e070034f35d984d06c675af8fee81fmindyp // Otherwise, assume they are just doing 1 and wait less time 544a44babdac4e070034f35d984d06c675af8fee81fmindyp fadeIn.startFadeInTextAnimation(sDismissAllShortDelay /* delay start */); 545a44babdac4e070034f35d984d06c675af8fee81fmindyp } 5464d4531a63cff536d2ee1a2929d0820981df8516amindyp } 54770f0111a4337367b0cd5fcc1302b730fb332aeebMark Wei Utils.traceEndSection(); 54884f9b5c60dc023570202859ba1d30cf9cb5e6e7aMindy Pereira return fadeIn; 5496c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5506c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5517c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 552067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (convertView != null && !(convertView instanceof SwipeableConversationItemView)) { 553067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira LogUtils.w(LOG_TAG, "Incorrect convert view received; nulling it out"); 554eb88ececd0a53c4e956240b7b619da6410e2d356mindyp convertView = newView(mContext, cursor, parent); 555c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira } else if (convertView != null) { 556c79aec78d06928b3fa1464d6aed60019f9b4843bMindy Pereira ((SwipeableConversationItemView) convertView).reset(); 557afd6f9246ddf645a45c8e91df5c5c2587cbf6a0dMindy Pereira } 558f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang final View v = createConversationItemView((SwipeableConversationItemView) convertView, 559f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao mContext, conv); 560f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceEndSection(); 561f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang return v; 5629879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 5639879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 5646c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private boolean hasLeaveBehinds() { 5656a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp return !mLeaveBehindItems.isEmpty(); 5666c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5676c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 56862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang private boolean hasFadeLeaveBehinds() { 5698f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira return !mFadeLeaveBehindItems.isEmpty(); 57062d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 57162d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 57279e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira public LeaveBehindItem setupLeaveBehind(Conversation target, ToastBarOperation undoOp, 573370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang int deletedRow, int viewHeight) { 5744d4531a63cff536d2ee1a2929d0820981df8516amindyp cancelLeaveBehindFadeInAnimation(); 5756a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = target.id; 57662d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang fadeOutLeaveBehindItems(); 577370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 578370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final LeaveBehindItem leaveBehind = (LeaveBehindItem) LayoutInflater.from(mContext) 579370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang .inflate(R.layout.swipe_leavebehind, mListView, false); 580370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang leaveBehind.bind(deletedRow, mAccount, this, undoOp, target, mFolder, viewHeight); 5816a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.put(target.id, leaveBehind); 582e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp mLastDeletingItems.add(target.id); 58379e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira return leaveBehind; 5846c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 5856c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 5866a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp public void fadeOutSpecificLeaveBehindItem(long id) { 5876a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == id) { 5886a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = -1; 5896a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 5906a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp startFadeOutLeaveBehindItemsAnimations(); 5916a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 5926a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp 5936a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // This should kick off a timer such that there is a minimum time each item 5946a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // shows up before being dismissed. That way if the user is swiping away 5956a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // items in rapid succession, their finger position is maintained. 59662d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang public void fadeOutLeaveBehindItems() { 5976a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mCountDown == null) { 5986a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mCountDown = new Runnable() { 5996a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp @Override 6006a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp public void run() { 6016a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp startFadeOutLeaveBehindItemsAnimations(); 6026a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6036a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp }; 6046a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } else { 6056a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mHandler.removeCallbacks(mCountDown); 6066a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6076a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp // Clear all the text since these are no longer clickable 6086a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Iterator<Entry<Long, LeaveBehindItem>> i = mLeaveBehindItems.entrySet().iterator(); 6096a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp LeaveBehindItem item; 6106a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp while (i.hasNext()) { 6116a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item = i.next().getValue(); 6126a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Conversation conv = item.getData(); 6136a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == -1 || conv.id != mLastLeaveBehind) { 614a44babdac4e070034f35d984d06c675af8fee81fmindyp item.cancelFadeInTextAnimation(); 6156a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.makeInert(); 6166a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6176a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6183b5e82b06a0af3f5ddf3667de9a2aa26eeb5f24bmindyp startDismissCounter(); 6196a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6206a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp 6216a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp protected void startFadeOutLeaveBehindItemsAnimations() { 62262d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang final int startPosition = mListView.getFirstVisiblePosition(); 62362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang final int endPosition = mListView.getLastVisiblePosition(); 62462d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 62579e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira if (hasLeaveBehinds()) { 62679e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira // If the item is visible, fade it out. Otherwise, just remove 62779e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira // it. 6286a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Iterator<Entry<Long, LeaveBehindItem>> i = mLeaveBehindItems.entrySet().iterator(); 6296a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp LeaveBehindItem item; 6306a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp while (i.hasNext()) { 6316a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item = i.next().getValue(); 6326a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp Conversation conv = item.getData(); 6336a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == -1 || conv.id != mLastLeaveBehind) { 6346a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (conv.position >= startPosition && conv.position <= endPosition) { 6356a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mFadeLeaveBehindItems.put(conv.id, item); 6366a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } else { 6376a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.commit(); 6386a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 6396a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp i.remove(); 6406a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 64162d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 6424d4531a63cff536d2ee1a2929d0820981df8516amindyp cancelLeaveBehindFadeInAnimation(); 64362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 64462d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang if (!mLastDeletingItems.isEmpty()) { 64562d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang mLastDeletingItems.clear(); 64662d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 64762d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang notifyDataSetChanged(); 64862d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 64962d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 6504d4531a63cff536d2ee1a2929d0820981df8516amindyp private void cancelLeaveBehindFadeInAnimation() { 6514d4531a63cff536d2ee1a2929d0820981df8516amindyp LeaveBehindItem leaveBehind = getLastLeaveBehindItem(); 6524d4531a63cff536d2ee1a2929d0820981df8516amindyp if (leaveBehind != null) { 6534d4531a63cff536d2ee1a2929d0820981df8516amindyp leaveBehind.cancelFadeInTextAnimation(); 6544d4531a63cff536d2ee1a2929d0820981df8516amindyp } 6554d4531a63cff536d2ee1a2929d0820981df8516amindyp } 6564d4531a63cff536d2ee1a2929d0820981df8516amindyp 6571aba32575a08da6cbad80af8446201d73c59783dMark Wei public CoordinatesCache getCoordinatesCache() { 658fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang return mCoordinatesCache; 659fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 660fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 6611801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein public BidiFormatter getBidiFormatter() { 6621801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein return mBidiFormatter; 6631801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein } 6641801b32a2977ca97ca194a3c9e9633b03e5496a4Andrew Sapperstein 6655254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp public SwipeableListView getListView() { 6665254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp return mListView; 6675254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 6685254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp 669c6adce3cf6887c4c6dd5005724565702751843d0mindyp public void commitLeaveBehindItems(boolean animate) { 670dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira // Remove any previously existing leave behinds. 6715254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp boolean changed = false; 67279e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira if (hasLeaveBehinds()) { 6736a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp for (LeaveBehindItem item : mLeaveBehindItems.values()) { 6746a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (animate) { 675dcb26aea2b27b585c35c422c870e849b8c4e41d6mindyp mFadeLeaveBehindItems.put(item.getConversationId(), item); 6766a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } else { 6776a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.commit(); 6786a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 679c6adce3cf6887c4c6dd5005724565702751843d0mindyp } 6805254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp changed = true; 6816a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = -1; 6826a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.clear(); 683dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira } 684aa55bc9cb210a46a950874f368baa07f041a4302mindyp if (hasFadeLeaveBehinds() && !animate) { 685aa55bc9cb210a46a950874f368baa07f041a4302mindyp // Find any fading leave behind items and commit them all, too. 686aa55bc9cb210a46a950874f368baa07f041a4302mindyp for (LeaveBehindItem item : mFadeLeaveBehindItems.values()) { 687aa55bc9cb210a46a950874f368baa07f041a4302mindyp item.commit(); 688aa55bc9cb210a46a950874f368baa07f041a4302mindyp } 689aa55bc9cb210a46a950874f368baa07f041a4302mindyp mFadeLeaveBehindItems.clear(); 690aa55bc9cb210a46a950874f368baa07f041a4302mindyp changed = true; 691aa55bc9cb210a46a950874f368baa07f041a4302mindyp } 69206b623852cdacc749d67d9c1b7c478dd52780297Mindy Pereira if (!mLastDeletingItems.isEmpty()) { 69306b623852cdacc749d67d9c1b7c478dd52780297Mindy Pereira mLastDeletingItems.clear(); 6945254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp changed = true; 6955254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 696fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy 697fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy for (final ConversationSpecialItemView view : mFleetingViews) { 698fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy if (view.commitLeaveBehindItem()) { 699fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy changed = true; 700fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy } 701fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy } 702fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy 7035254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp if (changed) { 7045254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp notifyDataSetChanged(); 70506b623852cdacc749d67d9c1b7c478dd52780297Mindy Pereira } 706dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira } 707dea5d77be4c6601b461b45fd06a92bb3e44b8810Mindy Pereira 70879e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira private LeaveBehindItem getLeaveBehindItem(Conversation target) { 7096a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp return mLeaveBehindItems.get(target.id); 7106c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 7116c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 71262d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang private LeaveBehindItem getFadeLeaveBehindItem(int position, Conversation target) { 7138f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira return mFadeLeaveBehindItems.get(target.id); 71462d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 71562d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 716d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira @Override 717d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira public long getItemId(int position) { 7180a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao if ((mHeaders.size() > position) || (position == getCount() - 1)) { 719d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira return -1; 720d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 721f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy 7220e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao final ConversationSpecialItemView specialView = mSpecialViews.get( 7230e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao getSpecialViewsPos(position)); 724f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy if (specialView != null) { 725f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy // TODO(skennedy) We probably want something better than this 726f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy return specialView.hashCode(); 727f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy } 728f77806ed36ab49861a5ea13a3ab34e5a3a21c022Scott Kennedy 72955e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang final int cursorPos = position - getPositionOffset(position); 730348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // advance the cursor to the right position and read the cached conversation, if present 731348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // 732348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // (no need to have CursorAdapter check mDataValid because in our incarnation without 733348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // FLAG_REGISTER_CONTENT_OBSERVER, mDataValid is effectively identical to mCursor being 734348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang // non-null) 735348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang final ConversationCursor cursor = getConversationCursor(); 736348398d7f3ff058248ef9f7d37443496c0e400a5Andy Huang if (cursor != null && cursor.moveToPosition(cursorPos)) { 7376cf45c601317d4b65ffb1896760fa1cb8a2b807cAndy Huang final Conversation conv = cursor.getCachedConversation(); 73855e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang if (conv != null) { 73955e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang return conv.id; 74055e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang } 74155e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang } 74255e76949ca7464c3bd55fdc25fb3daa43466ef5cAndy Huang return super.getItemId(cursorPos); 743d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 744d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira 7456176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy /** 7466176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy * @param position The position in the cursor 7476176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy */ 748e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private View getDeletingView(int position, Conversation conversation, ViewGroup parent, 749e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp boolean swipe) { 750c7d201d79974fd0f1e935880d51fe516f78207a2Vikram Aggarwal conversation.position = position; 751067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira SwipeableConversationItemView deletingView = mAnimatingViews.get(conversation.id); 752067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (deletingView == null) { 753067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // The undo animation consists of fading in the conversation that 754067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // had been destroyed. 755067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira deletingView = newConversationItemView(position, parent, conversation); 756370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang deletingView.startDeleteAnimation(mAnimatorListener, swipe); 757067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 758067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return deletingView; 759a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira } 760a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira 7616176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy /** 7626176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy * @param position The position in the cursor 7636176b722c53d0fa546f679cc453af615045b1e14Scott Kennedy */ 764e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private View getUndoingView(int position, Conversation conv, ViewGroup parent, boolean swipe) { 765e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp conv.position = position; 766e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp SwipeableConversationItemView undoView = mAnimatingViews.get(conv.id); 767067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (undoView == null) { 768067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // The undo animation consists of fading in the conversation that 769067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira // had been destroyed. 770e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp undoView = newConversationItemView(position, parent, conv); 771370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang undoView.startUndoAnimation(mAnimatorListener, swipe); 772067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 773067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return undoView; 774067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 775067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 7765ceab3bd6892b85b0252b987b67b70ec5055587fmindyp @Override 7775ceab3bd6892b85b0252b987b67b70ec5055587fmindyp public View newView(Context context, Cursor cursor, ViewGroup parent) { 7783dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao return new SwipeableConversationItemView(context, mAccount); 7795ceab3bd6892b85b0252b987b67b70ec5055587fmindyp } 7805ceab3bd6892b85b0252b987b67b70ec5055587fmindyp 7815ceab3bd6892b85b0252b987b67b70ec5055587fmindyp @Override 7825ceab3bd6892b85b0252b987b67b70ec5055587fmindyp public void bindView(View view, Context context, Cursor cursor) { 78307fe8df87bde8732398434e55cce366a8528c181Andy Huang // no-op. we only get here from newConversationItemView(), which will immediately bind 78407fe8df87bde8732398434e55cce366a8528c181Andy Huang // on its own. 7855ceab3bd6892b85b0252b987b67b70ec5055587fmindyp } 7865ceab3bd6892b85b0252b987b67b70ec5055587fmindyp 787067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private SwipeableConversationItemView newConversationItemView(int position, ViewGroup parent, 788067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira Conversation conversation) { 789067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira SwipeableConversationItemView view = (SwipeableConversationItemView) super.getView( 790067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira position, null, parent); 791dc0617f3478b21dd3324ab10b8c433517ae95460mindyp view.reset(); 792a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei view.bind(conversation, mActivity, mBatchConversations, mFolder, getCheckboxSetting(), 793f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao mSwipeEnabled, mImportanceMarkersEnabled, mShowChevronsEnabled, this); 794067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira mAnimatingViews.put(conversation.id, view); 795067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return view; 7969879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 7979879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 798642731419abb9037a729114d32d6ddd15af0a406Alice Yang private int getCheckboxSetting() { 799642731419abb9037a729114d32d6ddd15af0a406Alice Yang return mAccount != null ? mAccount.settings.convListIcon : 800642731419abb9037a729114d32d6ddd15af0a406Alice Yang ConversationListIcon.DEFAULT; 801642731419abb9037a729114d32d6ddd15af0a406Alice Yang } 802642731419abb9037a729114d32d6ddd15af0a406Alice Yang 803d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira @Override 804d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira public Object getItem(int position) { 8050e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao final ConversationSpecialItemView specialView = mSpecialViews.get( 8060e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao getSpecialViewsPos(position)); 807eb145d45c17b08ce09131e84b96350925b3db81aJin Cao if (mHeaders.size() > position) { 808eb145d45c17b08ce09131e84b96350925b3db81aJin Cao return mHeaders.get(position); 8090a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao } else if (position == getCount() - 1) { 8100a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao return mShowCustomFooter ? mFooter : mDefaultFooter; 8110e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao } else if (specialView != null) { 8120e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao return specialView; 813d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 8147c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy return super.getItem(position - getPositionOffset(position)); 815d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira } 816d3651a6ad41c1451e90f538b9f66afb008a44216Mindy Pereira 817e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionDeleting(long id) { 818e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mDeletingItems.contains(id); 819a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira } 820a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira 821e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionSwipeDeleting(long id) { 822e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mSwipeDeletingItems.contains(id); 823067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 824067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 825e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionUndoing(long id) { 826e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mUndoingItems.contains(id); 8279879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 8289879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira 829e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private boolean isPositionUndoingSwipe(long id) { 830e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp return mSwipeUndoingItems.contains(id); 831bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 832bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 8336c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira private boolean isPositionLeaveBehind(Conversation conv) { 83479e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira return hasLeaveBehinds() 8356a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp && mLeaveBehindItems.containsKey(conv.id) 83679e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira && conv.isMostlyDead(); 8376c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 8386c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 83962d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang private boolean isPositionFadeLeaveBehind(Conversation conv) { 84079e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira return hasFadeLeaveBehinds() 8418f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira && mFadeLeaveBehindItems.containsKey(conv.id) 84279e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira && conv.isMostlyDead(); 84362d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang } 84462d7962b2b4d73f8414bbab1f42952442ac25be0Andy Huang 845c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal /** 846c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * Performs the pending destruction, if any and assigns the next pending action. 847c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * @param next The next action that is to be performed, possibly null (if no next action is 848c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal * needed). 849c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal */ 85037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal private void performAndSetNextAction(ListItemsRemovedListener next) { 851c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal if (mPendingDestruction != null) { 8529365a826b46b0e274df88e92534f7d871eef2aa2mindyp mPendingDestruction.onListItemsRemoved(); 853c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal } 854c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal mPendingDestruction = next; 855c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal } 856c30fe4172676a5ea3fdc0da8a0fbb917d9cf878eVikram Aggarwal 857e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp private void updateAnimatingConversationItems(Object obj, HashSet<Long> items) { 858067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (!items.isEmpty()) { 859067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (obj instanceof ConversationItemView) { 860067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira final ConversationItemView target = (ConversationItemView) obj; 861e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp final long id = target.getConversation().id; 862e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp items.remove(id); 863e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp mAnimatingViews.remove(id); 864067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira if (items.isEmpty()) { 865bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira performAndSetNextAction(null); 866067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira notifyDataSetChanged(); 867bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 868866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 8699879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira } 870bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 871bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 8729879d4c74520800eff386ab27eb5e03432c610b5Mindy Pereira @Override 873866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public boolean areAllItemsEnabled() { 87437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal // The animating items and some special views are not enabled. 875866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return false; 876866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 877866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 878866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira @Override 879b90db28aac1311f0ed32a786594e17c007550853Scott Kennedy public boolean isEnabled(final int position) { 88037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final ConversationSpecialItemView view = mSpecialViews.get(position); 88137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal if (view != null) { 88237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final boolean enabled = view.acceptsUserTaps(); 88337a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal LogUtils.d(LOG_TAG, "AA.isEnabled(%d) = %b", position, enabled); 88437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal return enabled; 885b90db28aac1311f0ed32a786594e17c007550853Scott Kennedy } 886a41baad67f0e49a53e67ae560d130dc463bba4f8Mindy Pereira return !isPositionDeleting(position) && !isPositionUndoing(position); 887866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 888866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 889573b9e698852c6cf2cbf0f93bc01b7abb8b64ce1Paul Westbrook public void setFooterVisibility(boolean show) { 8900a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao if (mShowCustomFooter != show) { 8910a72b736dae35dc6a8a0d38a9a6e8a17607a9d25Jin Cao mShowCustomFooter = show; 8926681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira notifyDataSetChanged(); 8936681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 8946681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 8956681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira 8966681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira public void addFooter(View footerView) { 8976681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira mFooter = footerView; 8986681f6b78557850d9ec76a7a8f9ac1ec930d2513Mindy Pereira } 8994584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira 900eb145d45c17b08ce09131e84b96350925b3db81aJin Cao public void addHeader(View headerView) { 901eb145d45c17b08ce09131e84b96350925b3db81aJin Cao mHeaders.add(headerView); 902eb145d45c17b08ce09131e84b96350925b3db81aJin Cao } 903eb145d45c17b08ce09131e84b96350925b3db81aJin Cao 9044584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira public void setFolder(Folder folder) { 9054584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira mFolder = folder; 9064584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira } 9076c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira 90879e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira public void clearLeaveBehind(long itemId) { 9096a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (hasLeaveBehinds() && mLeaveBehindItems.containsKey(itemId)) { 9106a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.remove(itemId); 9118f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira } else if (hasFadeLeaveBehinds()) { 9128f39702ca9f9bea23d27a46a288cd6f6660de447Mindy Pereira mFadeLeaveBehindItems.remove(itemId); 91379e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } else { 91479e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira LogUtils.d(LOG_TAG, "Trying to clear a non-existant leave behind"); 91579e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } 9166a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == itemId) { 9176a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLastLeaveBehind = -1; 9186a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 9196c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 9207d81600cbce3cfd366cbff9ecd1b7317ff957221Vikram Aggarwal 921d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira public void onSaveInstanceState(Bundle outState) { 922e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp long[] lastDeleting = new long[mLastDeletingItems.size()]; 92379e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira for (int i = 0; i < lastDeleting.length; i++) { 924d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira lastDeleting[i] = mLastDeletingItems.get(i); 925d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 926e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp outState.putLongArray(LAST_DELETING_ITEMS, lastDeleting); 92779e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira if (hasLeaveBehinds()) { 9286a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind != -1) { 9296a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp outState.putParcelable(LEAVE_BEHIND_ITEM_DATA, 9306a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.get(mLastLeaveBehind).getLeaveBehindData()); 9316a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp outState.putLong(LEAVE_BEHIND_ITEM_ID, mLastLeaveBehind); 9326a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 9336a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp for (LeaveBehindItem item : mLeaveBehindItems.values()) { 9346a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (mLastLeaveBehind == -1 || item.getData().id != mLastLeaveBehind) { 9356a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp item.commit(); 9366a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 9376a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp } 93879e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } 939d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 940d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira 941d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira public void onRestoreInstanceState(Bundle outState) { 942b8ef4ac43f3570245ec476e2ee9f8a9d1d3ff36cPaul Westbrook if (outState.containsKey(LAST_DELETING_ITEMS)) { 943e85b8cdf23ba579246a1c8c3774687ca614eb39bmindyp final long[] lastDeleting = outState.getLongArray(LAST_DELETING_ITEMS); 94437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final long aLastDeleting : lastDeleting) { 94537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mLastDeletingItems.add(aLastDeleting); 946b8ef4ac43f3570245ec476e2ee9f8a9d1d3ff36cPaul Westbrook } 947d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 9486a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp if (outState.containsKey(LEAVE_BEHIND_ITEM_DATA)) { 9496a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp LeaveBehindData left = 9506a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp (LeaveBehindData) outState.getParcelable(LEAVE_BEHIND_ITEM_DATA); 9516a6deb20dbbea543ccf093487d26dea4ac4f9cd4mindyp mLeaveBehindItems.put(outState.getLong(LEAVE_BEHIND_ITEM_ID), 952370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang setupLeaveBehind(left.data, left.op, left.data.position, left.height)); 95379e6a0830cc23deb9ba7be07d4ec5b5235a3398bMindy Pereira } 954d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira } 95569e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira 95669e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira /** 95769e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira * Return if the adapter is in the process of animating anything. 95869e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira */ 95969e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira public boolean isAnimating() { 96069e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira return !mUndoingItems.isEmpty() 96169e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira || !mSwipeUndoingItems.isEmpty() 9621e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira || hasFadeLeaveBehinds() 96369e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira || !mDeletingItems.isEmpty() 96469e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira || !mSwipeDeletingItems.isEmpty(); 96569e88dd6779a8f88212a049d49d69503cd746ef7Mindy Pereira } 966215d2a465dd17139d4c8cce426ae8c8ff556746emindyp 967f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang /** 968f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang * Forcibly clear any internal state that would cause {@link #isAnimating()} to return true. 969f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang * Call this in times of desperation, when you really, really want to trash state and just 970f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang * start over. 971f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang */ 972f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang public void clearAnimationState() { 973f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang if (!isAnimating()) { 974f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang return; 975f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang } 976f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang 977f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mUndoingItems.clear(); 978f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mSwipeUndoingItems.clear(); 979f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mFadeLeaveBehindItems.clear(); 980f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mDeletingItems.clear(); 981f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mSwipeDeletingItems.clear(); 982f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang mAnimatingViews.clear(); 983f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang LogUtils.w(LOG_TAG, "AA.clearAnimationState forcibly cleared state, this=%s", this); 984f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang } 985f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang 986c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang @Override 987c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang public String toString() { 988c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang final StringBuilder sb = new StringBuilder("{"); 989c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(super.toString()); 990c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mUndoingItems="); 991c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mUndoingItems); 992c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mSwipeUndoingItems="); 993c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mSwipeUndoingItems); 994c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mDeletingItems="); 995c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mDeletingItems); 996c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mSwipeDeletingItems="); 997c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mSwipeDeletingItems); 998c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mLeaveBehindItems="); 999c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mLeaveBehindItems); 1000c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mFadeLeaveBehindItems="); 1001c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mFadeLeaveBehindItems); 1002c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(" mLastDeletingItems="); 1003c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append(mLastDeletingItems); 1004f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(" mAnimatingViews="); 1005f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(mAnimatingViews); 1006f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(" mPendingDestruction="); 1007f21787ad2ac7d68e3620ffa3ae6e8e7fadf0bd54Andy Huang sb.append(mPendingDestruction); 1008c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang sb.append("}"); 1009c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang return sb.toString(); 1010c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang } 1011c1922a93fb9540d4ff8c28a30d1ae58d3a3d73f9Andy Huang 1012215d2a465dd17139d4c8cce426ae8c8ff556746emindyp /** 1013215d2a465dd17139d4c8cce426ae8c8ff556746emindyp * Get the ConversationCursor associated with this adapter. 1014215d2a465dd17139d4c8cce426ae8c8ff556746emindyp */ 1015215d2a465dd17139d4c8cce426ae8c8ff556746emindyp public ConversationCursor getConversationCursor() { 1016215d2a465dd17139d4c8cce426ae8c8ff556746emindyp return (ConversationCursor) getCursor(); 1017215d2a465dd17139d4c8cce426ae8c8ff556746emindyp } 10187af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp 10194d4531a63cff536d2ee1a2929d0820981df8516amindyp /** 10204d4531a63cff536d2ee1a2929d0820981df8516amindyp * Get the currently visible leave behind item. 10214d4531a63cff536d2ee1a2929d0820981df8516amindyp */ 10227af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp public LeaveBehindItem getLastLeaveBehindItem() { 10237af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp if (mLastLeaveBehind != -1) { 10247af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return mLeaveBehindItems.get(mLastLeaveBehind); 10257af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 10267af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp return null; 10277af43c93d4ca90bb0a43ec790a434c95128cc99fmindyp } 10284d4531a63cff536d2ee1a2929d0820981df8516amindyp 10294d4531a63cff536d2ee1a2929d0820981df8516amindyp /** 10304d4531a63cff536d2ee1a2929d0820981df8516amindyp * Cancel fading out the text displayed in the leave behind item currently 10314d4531a63cff536d2ee1a2929d0820981df8516amindyp * shown. 10324d4531a63cff536d2ee1a2929d0820981df8516amindyp */ 10334d4531a63cff536d2ee1a2929d0820981df8516amindyp public void cancelFadeOutLastLeaveBehindItemText() { 10344d4531a63cff536d2ee1a2929d0820981df8516amindyp LeaveBehindItem item = getLastLeaveBehindItem(); 10354d4531a63cff536d2ee1a2929d0820981df8516amindyp if (item != null) { 10364d4531a63cff536d2ee1a2929d0820981df8516amindyp item.cancelFadeOutText(); 10374d4531a63cff536d2ee1a2929d0820981df8516amindyp } 10384d4531a63cff536d2ee1a2929d0820981df8516amindyp } 10397c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 104037a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal /** 10411c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy * Updates special (non-conversation view) when {@link #mFleetingViews} changed 104237a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal */ 10437c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy private void updateSpecialViews() { 10441c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // We recreate all the special views using mFleetingViews. 104537a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mSpecialViews.clear(); 104637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal 1047bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao // If the conversation cursor hasn't finished loading, hide all special views 1048bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao if (!ConversationCursor.isCursorReadyToShow(getConversationCursor())) { 1049bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao return; 1050bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao } 1051bc29ed3a5fe96ac144d5157150551febfb4d1355Jin Cao 10521c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Fleeting (temporary) views specify a position, which is 0-indexed and 10531c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // has to be adjusted for the number of fleeting views above it. 105437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView specialView : mFleetingViews) { 10550e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy specialView.onUpdate(mFolder, getConversationCursor()); 10567c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10577c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy if (specialView.getShouldDisplayInList()) { 10580e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // If the special view asks for position 0, it wants to be at the top. 10590e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy int position = (specialView.getPosition()); 10602102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei 10612102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei // insert the special view into the position, but if there is 10622102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei // already an item occupying that position, move that item back 10632102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei // one position, and repeat 10642102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei ConversationSpecialItemView insert = specialView; 10652102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei while (insert != null) { 106637a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal final ConversationSpecialItemView kickedOut = mSpecialViews.get(position); 106737a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal mSpecialViews.put(position, insert); 10682102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei insert = kickedOut; 10692102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei position++; 10702102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei } 10717c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10727c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10737c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10747c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 1075e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy /** 1076e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * Gets the position of the specified {@link ConversationSpecialItemView}, as determined by 1077e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * the adapter. 1078e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * 1079e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy * @return The position in the list, or a negative value if it could not be found 1080e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy */ 1081e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy public int getSpecialViewPosition(final ConversationSpecialItemView view) { 1082e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy return mSpecialViews.indexOfValue(view); 1083e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy } 1084e0d01fb7379225a0f058999d9da9050f2fcc6945Scott Kennedy 10857c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 10867c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void notifyDataSetChanged() { 1087d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy // This may be a temporary catch for a problem, or we may leave it here. 1088d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy // b/9527863 1089d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy if (Looper.getMainLooper() != Looper.myLooper()) { 1090d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy LogUtils.wtf(LOG_TAG, "notifyDataSetChanged() called off the main thread"); 1091d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy } 1092d54a43c1d722ad7cb0376ba801c59c69d8a70234Scott Kennedy 10937c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 10947c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy super.notifyDataSetChanged(); 10957c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 10967c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 10977c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 10987c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void changeCursor(final Cursor cursor) { 10997c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy super.changeCursor(cursor); 11007c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 11017c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11027c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11037c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 11047c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void changeCursorAndColumns(final Cursor c, final String[] from, final int[] to) { 11057c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy super.changeCursorAndColumns(c, from, to); 11067c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 11077c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11087c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11097c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy @Override 11107c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public Cursor swapCursor(final Cursor c) { 11117c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy final Cursor oldCursor = super.swapCursor(c); 11127c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy updateSpecialViews(); 11137c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11147c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy return oldCursor; 11157c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11167c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 1117a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei public BitmapCache getSendersImagesCache() { 1118a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei return mSendersImagesCache; 111979c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 112079c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 1121a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei public ContactResolver getContactResolver() { 1122a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei return mContactResolver; 112365b6d180f50922a3393795203cae68a5a2f6a33dMark Wei } 112465b6d180f50922a3393795203cae68a5a2f6a33dMark Wei 11257c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy /** 11267c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy * Gets the offset for the given position in the underlying cursor, based on any special views 11277c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy * that may be above it. 11287c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy */ 11290e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao public int getPositionOffset(int position) { 1130eb145d45c17b08ce09131e84b96350925b3db81aJin Cao int viewsAbove = mHeaders.size(); 11317c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11320e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao position -= viewsAbove; 1133da8b096b6a9128dc7c7e7d4fd46d48f9a594268dMark Wei for (int i = 0, size = mSpecialViews.size(); i < size; i++) { 113418310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal final int bidPosition = mSpecialViews.keyAt(i); 113518310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal // If the view bid for a position above the cursor position, 11360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // it is above the conversation. 11370e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (bidPosition <= position) { 113818310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal viewsAbove++; 11397c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11407c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11417c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 114218310f861218587fd8c5a5b270a20f29380af462Vikram Aggarwal return viewsAbove; 11437c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11447c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy 11450e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao /** 11460e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao * Gets the correct position for special views given the number of headers we have. 11470e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao */ 11480e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao private int getSpecialViewsPos(final int position) { 11490e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao return position - mHeaders.size(); 11500e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao } 11510e424db6bc5cfbb7f8d980fb9d184f0835bb1fe3Jin Cao 11527c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy public void cleanup() { 11531c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Clean up teaser views. 115437a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView view : mFleetingViews) { 11557c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy view.cleanup(); 11567c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 11577c8325de829ca029ce4547e4f0fa266124301367Scott Kennedy } 1158fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang 1159fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang public void onConversationSelected() { 11601c2676be24de6e490a149aeea0cf0f4499887751Scott Kennedy // Notify teaser views. 116137a20ca39be842b4b4cb54d5b5ed418d49d950cfVikram Aggarwal for (final ConversationSpecialItemView specialView : mFleetingViews) { 1162fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang specialView.onConversationSelected(); 1163fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang } 1164fe8e081d6230f343dc74b45d69e5f4634a332b5aAlice Yang } 11652f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein 11662f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein public void onCabModeEntered() { 1167a2f1922c41eb5a01f1972c49ab80019a72f1aa0fAndrew Sapperstein for (final ConversationSpecialItemView specialView : mFleetingViews) { 11682f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein specialView.onCabModeEntered(); 11692f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein } 11702f542873183b37fa38a0d468f46bbfebc1f537e2Andrew Sapperstein } 117179c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 1172cc139833bc5829ba70244519e9870de783c41848Scott Kennedy public void onCabModeExited() { 1173cc139833bc5829ba70244519e9870de783c41848Scott Kennedy for (final ConversationSpecialItemView specialView : mFleetingViews) { 1174cc139833bc5829ba70244519e9870de783c41848Scott Kennedy specialView.onCabModeExited(); 1175cc139833bc5829ba70244519e9870de783c41848Scott Kennedy } 1176cc139833bc5829ba70244519e9870de783c41848Scott Kennedy } 1177cc139833bc5829ba70244519e9870de783c41848Scott Kennedy 117832ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy public void onConversationListVisibilityChanged(final boolean visible) { 117932ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy for (final ConversationSpecialItemView specialView : mFleetingViews) { 118032ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy specialView.onConversationListVisibilityChanged(visible); 118132ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 118232ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 118332ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy 1184f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy public int getViewMode() { 1185f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy return mActivity.getViewMode().getMode(); 1186f45e0e7f65eb421fc5c2acf7bb76a714e12dc68bScott Kennedy } 118759bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy 118859bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy public boolean isInCabMode() { 118959bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy // If we have conversation in our selected set, we're in CAB mode 119059bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy return !mBatchConversations.isEmpty(); 119159bd7d331b38322dbe760be7a96c84ea832406c4Scott Kennedy } 119232ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy 119332ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy public void saveSpecialItemInstanceState(final Bundle outState) { 119432ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy for (final ConversationSpecialItemView specialView : mFleetingViews) { 119532ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy specialView.saveInstanceState(outState); 119632ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 119732ddb84f2d4f53bfc4b53656461068c0c69d6325Scott Kennedy } 11987ed53776a053782ca37303075c144926647ac557Paul Westbrook} 1199