10e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy/* 20e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * Copyright (C) 2013 Google Inc. 30e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * Licensed to The Android Open Source Project. 40e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * 50e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * Licensed under the Apache License, Version 2.0 (the "License"); 60e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * you may not use this file except in compliance with the License. 70e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * You may obtain a copy of the License at 80e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * 90e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * http://www.apache.org/licenses/LICENSE-2.0 100e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * 110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * Unless required by applicable law or agreed to in writing, software 120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * See the License for the specific language governing permissions and 150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * limitations under the License. 160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 170e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedypackage com.android.mail.ui; 180e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 190e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.app.LoaderManager; 200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.app.LoaderManager.LoaderCallbacks; 210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.content.Context; 220e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.content.Loader; 230e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.content.res.Resources; 240e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.net.Uri; 250e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.os.Bundle; 26a6e29eca5965025f2f788929834c01cc345d7670Andrew Sappersteinimport android.support.v4.text.BidiFormatter; 270e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.support.v4.util.SparseArrayCompat; 280e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.text.TextUtils; 290e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.util.AttributeSet; 300e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.view.LayoutInflater; 310e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.view.View; 320e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.view.ViewGroup; 330e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.widget.ImageView; 340e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.widget.LinearLayout; 350e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport android.widget.TextView; 360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 37821e578a71c7015646522e729600618f0ec16fc0Tony Mantlerimport com.android.emailcommon.mail.Address; 380e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.R; 390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.browse.ConversationCursor; 400e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.content.ObjectCursor; 410e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.content.ObjectCursorLoader; 420e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.providers.Account; 430e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.providers.Conversation; 440e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.providers.Folder; 453b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieuximport com.android.mail.providers.ParticipantInfo; 460e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.providers.UIProvider; 470e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.providers.UIProvider.AccountCapabilities; 480e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.providers.UIProvider.ConversationListQueryParameters; 490e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.utils.LogUtils; 500e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.android.mail.utils.Utils; 510e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.google.common.collect.ImmutableList; 520e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.google.common.collect.ImmutableSortedSet; 530e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.google.common.collect.Lists; 540e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport com.google.common.collect.Maps; 550e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 560e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport java.util.ArrayList; 5742fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantlerimport java.util.Collections; 580e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport java.util.Comparator; 590e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport java.util.List; 600e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedyimport java.util.Map; 610e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 620e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy/** 630e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * The teaser list item in the conversation list that shows nested folders. 640e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 650e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedypublic class NestedFolderTeaserView extends LinearLayout implements ConversationSpecialItemView { 660e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static final String LOG_TAG = "NestedFolderTeaserView"; 670e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 680e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private boolean mShouldDisplayInList = false; 690e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 700e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private Account mAccount; 710e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private Uri mFolderListUri; 720e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private FolderSelector mListener; 730e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 740e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private LoaderManager mLoaderManager = null; 750e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private AnimatedAdapter mAdapter = null; 760e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 770e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final SparseArrayCompat<FolderHolder> mFolderHolders = 780e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy new SparseArrayCompat<FolderHolder>(); 794c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao private ImmutableSortedSet<FolderHolder> mSortedFolderHolders; 800e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 810e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final int mFolderItemUpdateDelayMs; 820e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 834c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao private final LayoutInflater mInflater; 840e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private ViewGroup mNestedFolderContainer; 850e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 860e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private View mShowMoreFoldersRow; 874c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao private ImageView mShowMoreFoldersIcon; 880e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private TextView mShowMoreFoldersTextView; 890e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private TextView mShowMoreFoldersCountTextView; 900e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 910e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /** 920e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * If <code>true</code> we show a limited set of folders, and a means to show all folders. If 930e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * <code>false</code>, we show all folders. 940e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 950e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private boolean mCollapsed = true; 960e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 970e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /** If <code>true</code>, the list of folders has updated since the view was last shown. */ 980e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private boolean mListUpdated; 990e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1000e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Each folder's loader will be this value plus the folder id 1010e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static final int LOADER_FOLDER_LIST = 1020e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy AbstractActivityController.LAST_FRAGMENT_LOADER_ID + 100000; 1030e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1040e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /** 1050e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * The maximum number of senders to show in the sender snippet. 1060e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 1070e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static final String MAX_SENDERS = "20"; 1080e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1090e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /** 1100e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * The number of folders to show when the teaser is collapsed. 1110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 1120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static int sCollapsedFolderThreshold = -1; 1130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static class FolderHolder { 1150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final View mItemView; 1160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final TextView mSendersTextView; 1170e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final TextView mCountTextView; 1187614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah private final ImageView mFolderIconImageView; 1190e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private Folder mFolder; 1200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private List<String> mUnreadSenders = ImmutableList.of(); 1210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1220e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public FolderHolder(final View itemView, final TextView sendersTextView, 1237614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah final TextView countTextView, final ImageView folderIconImageView) { 1240e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mItemView = itemView; 1250e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mSendersTextView = sendersTextView; 1260e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mCountTextView = countTextView; 1277614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah mFolderIconImageView = folderIconImageView; 1280e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1290e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1300e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void setFolder(final Folder folder) { 1310e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mFolder = folder; 1320e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1330e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1340e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public View getItemView() { 1350e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return mItemView; 1360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1370e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1380e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public TextView getSendersTextView() { 1390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return mSendersTextView; 1400e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1410e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1420e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public TextView getCountTextView() { 1430e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return mCountTextView; 1440e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1450e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1467614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah public ImageView getFolderIconImageView() { return mFolderIconImageView; } 1477614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah 1480e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public Folder getFolder() { 1490e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return mFolder; 1500e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1510e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1520e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /** 1530e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * @return a {@link List} of senders of unread messages 1540e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 1550e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public List<String> getUnreadSenders() { 1560e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return mUnreadSenders; 1570e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1580e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1590e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void setUnreadSenders(final List<String> unreadSenders) { 1600e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mUnreadSenders = unreadSenders; 1610e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1620e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1630e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public static final Comparator<FolderHolder> NAME_COMPARATOR = 1640e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy new Comparator<FolderHolder>() { 1650e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 1660e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public int compare(final FolderHolder lhs, final FolderHolder rhs) { 1670e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return lhs.getFolder().name.compareTo(rhs.getFolder().name); 1680e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1690e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy }; 1700e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1710e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1720e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public NestedFolderTeaserView(final Context context) { 1730e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy this(context, null); 1740e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1750e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1760e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public NestedFolderTeaserView(final Context context, final AttributeSet attrs) { 1770e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy this(context, attrs, -1); 1780e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1790e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1800e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public NestedFolderTeaserView( 1810e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Context context, final AttributeSet attrs, final int defStyle) { 1820e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy super(context, attrs, defStyle); 1830e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1840e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Resources resources = context.getResources(); 1850e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1860e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (sCollapsedFolderThreshold < 0) { 1870e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy sCollapsedFolderThreshold = 1880e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy resources.getInteger(R.integer.nested_folders_collapse_threshold); 1890e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1900e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1914c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mFolderItemUpdateDelayMs = resources.getInteger(R.integer.folder_item_refresh_delay_ms); 1924c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mInflater = LayoutInflater.from(context); 1930e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 1940e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1950e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 1960e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy protected void onFinishInflate() { 1970e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mNestedFolderContainer = (ViewGroup) findViewById(R.id.nested_folder_container); 1980e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 1990e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersRow = findViewById(R.id.show_more_folders_row); 2000e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersRow.setOnClickListener(mShowMoreOnClickListener); 2010e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2024c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mShowMoreFoldersIcon = 2034c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao (ImageView) mShowMoreFoldersRow.findViewById(R.id.show_more_folders_icon); 2044c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mShowMoreFoldersTextView = 2054c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao (TextView) mShowMoreFoldersRow.findViewById(R.id.show_more_folders_textView); 2060e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersCountTextView = 2074c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao (TextView) mShowMoreFoldersRow.findViewById(R.id.show_more_folders_count_textView); 2080e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2090e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2100e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void bind(final Account account, final FolderSelector listener) { 2110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mAccount = account; 2120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mListener = listener; 2130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /** 2160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * Creates a {@link FolderHolder}. 2170e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 2180e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private FolderHolder createFolderHolder(final CharSequence folderName) { 2194c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao final View itemView = mInflater.inflate(R.layout.folder_teaser_item, mNestedFolderContainer, 2204c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao false /* attachToRoot */); 2210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2220e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy ((TextView) itemView.findViewById(R.id.folder_textView)).setText(folderName); 2230e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final TextView sendersTextView = (TextView) itemView.findViewById(R.id.senders_textView); 2246092c62b65cefbc4fc856fce5921d9aa74eb444eRohan Shah final TextView countTextView = (TextView) itemView.findViewById(R.id.unread_count_textView); 2257614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah final ImageView folderIconImageView = 2267614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah (ImageView) itemView.findViewById(R.id.nested_folder_icon); 2277614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah final FolderHolder holder = new FolderHolder(itemView, sendersTextView, countTextView, 2287614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah folderIconImageView); 2296092c62b65cefbc4fc856fce5921d9aa74eb444eRohan Shah countTextView.setVisibility(View.VISIBLE); 2300e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy attachOnClickListener(itemView, holder); 2310e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2320e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return holder; 2330e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2340e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2350e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private void attachOnClickListener(final View view, final FolderHolder holder) { 2360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy view.setOnClickListener(new OnClickListener() { 2370e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 2380e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onClick(final View v) { 2390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mListener.onFolderSelected(holder.getFolder()); 2400e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2410e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy }); 2420e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2430e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2440e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 2450e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onUpdate(final Folder folder, final ConversationCursor cursor) { 2460e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShouldDisplayInList = false; // Assume disabled 2470e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2480e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (folder == null) { 2490e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return; 2500e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2510e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2520e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Uri folderListUri = folder.childFoldersListUri; 2530e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (folderListUri == null) { 2540e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return; 2550e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2560e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2570e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // If we don't support nested folders, don't show this view 2580e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (!mAccount.supportsCapability(AccountCapabilities.NESTED_FOLDERS)) { 2590e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return; 2600e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2610e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2620e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (mFolderListUri == null || !mFolderListUri.equals(folder.childFoldersListUri)) { 2630e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // We have a new uri 2640e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mFolderListUri = folderListUri; 2650e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2660e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Restart the loader 2670e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mLoaderManager.destroyLoader(LOADER_FOLDER_LIST); 2680e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mLoaderManager.initLoader(LOADER_FOLDER_LIST, null, mFolderListLoaderCallbacks); 2690e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2700e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2710e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShouldDisplayInList = true; // Now we know we have something to display 2720e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2730e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2740e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 2750e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onGetView() { 2760e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (mListUpdated) { 2770e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Clear out the folder views 2780e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mNestedFolderContainer.removeAllViews(); 2790e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2804c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // We either show all folders if it's not over the threshold, or we show none. 2814c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao if (mSortedFolderHolders.size() <= sCollapsedFolderThreshold || !mCollapsed) { 2824c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao for (final FolderHolder folderHolder : mSortedFolderHolders) { 2834c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mNestedFolderContainer.addView(folderHolder.getItemView()); 2840e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2850e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2860e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2870e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy updateShowMoreView(); 2880e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mListUpdated = false; 2890e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2900e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2910e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 2920e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final OnClickListener mShowMoreOnClickListener = new OnClickListener() { 2930e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 2940e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onClick(final View v) { 2950e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mCollapsed = !mCollapsed; 2960e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mListUpdated = true; 2970e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mAdapter.notifyDataSetChanged(); 2980e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 2990e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy }; 3000e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3010e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private void updateShowMoreView() { 3020e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int total = mFolderHolders.size(); 3030e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int displayed = mNestedFolderContainer.getChildCount(); 3040e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3054c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao if (displayed == 0) { 3060e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // We are not displaying all the folders 3070e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersRow.setVisibility(VISIBLE); 3084c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mShowMoreFoldersIcon.setImageResource(R.drawable.ic_drawer_folder_24dp); 3090e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersTextView.setText(String.format( 3104c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao getContext().getString(R.string.show_n_more_folders), total)); 3110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersCountTextView.setVisibility(VISIBLE); 3120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Get a count of unread messages in other folders 3140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy int unreadCount = 0; 3150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy for (int i = 0; i < mFolderHolders.size(); i++) { 3160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final FolderHolder holder = mFolderHolders.valueAt(i); 3174c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // TODO(skennedy) We want a "nested" unread count, that includes the unread 3184c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // count of nested folders 3194c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao unreadCount += holder.getFolder().unreadCount; 3200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersCountTextView.setText(Integer.toString(unreadCount)); 3224c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao } else if (displayed > sCollapsedFolderThreshold) { 3230e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // We are expanded 3240e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersRow.setVisibility(VISIBLE); 3254c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mShowMoreFoldersIcon.setImageResource(R.drawable.ic_collapse_24dp); 3260e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersTextView.setText(R.string.hide_folders); 3270e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersCountTextView.setVisibility(GONE); 3280e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } else { 3290e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // We don't need to collapse the folders 3300e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mShowMoreFoldersRow.setVisibility(GONE); 3310e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3320e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3330e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3340e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private void updateViews(final FolderHolder folderHolder) { 3350e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Folder folder = folderHolder.getFolder(); 3360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3374c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // Update unread count 3380e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final String unreadText = Utils.getUnreadCountString(getContext(), folder.unreadCount); 3390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy folderHolder.getCountTextView().setText(unreadText.isEmpty() ? "0" : unreadText); 3400e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3414c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // Update unread senders 342a6e29eca5965025f2f788929834c01cc345d7670Andrew Sapperstein final String sendersText = TextUtils.join( 343a6e29eca5965025f2f788929834c01cc345d7670Andrew Sapperstein getResources().getString(R.string.enumeration_comma), 344a6e29eca5965025f2f788929834c01cc345d7670Andrew Sapperstein folderHolder.getUnreadSenders()); 3454c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao final TextView sendersTextView = folderHolder.getSendersTextView(); 3464c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao if (!TextUtils.isEmpty(sendersText)) { 3474c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao sendersTextView.setVisibility(VISIBLE); 3484c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao sendersTextView.setText(sendersText); 3494c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao } else { 3504c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao sendersTextView.setVisibility(GONE); 3514c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao } 3520e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3530e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3540e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3550e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public boolean getShouldDisplayInList() { 3560e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return mShouldDisplayInList; 3570e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3580e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3590e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3600e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public int getPosition() { 3610e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return 0; 3620e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3630e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3640e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3650e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void setAdapter(final AnimatedAdapter adapter) { 3660e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mAdapter = adapter; 3670e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3680e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3690e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3700e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void bindFragment(final LoaderManager loaderManager, final Bundle savedInstanceState) { 3710e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (mLoaderManager != null) { 3720e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy throw new IllegalStateException("This view has already been bound to a LoaderManager."); 3730e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3740e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3750e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mLoaderManager = loaderManager; 3760e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3770e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3780e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3790e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void cleanup() { 3800e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 3810e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3820e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3830e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3840e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onConversationSelected() { 3850e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 3860e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3870e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3880e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3890e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onCabModeEntered() { 3900e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 3910e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3920e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3930e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3940e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onCabModeExited() { 3950e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 3960e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 3970e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 3980e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 3990e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onConversationListVisibilityChanged(final boolean visible) { 4000e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 4010e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4020e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4030e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 4040e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void saveInstanceState(final Bundle outState) { 4050e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 4060e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4070e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4080e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 4090e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public boolean acceptsUserTaps() { 4100e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // The teaser does not allow user tap in the list. 4110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return false; 4120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static int getLoaderId(final int folderId) { 4150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return folderId + LOADER_FOLDER_LIST; 4160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4170e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4180e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private static int getFolderId(final int loaderId) { 4190e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return loaderId - LOADER_FOLDER_LIST; 4200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4220e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final LoaderCallbacks<ObjectCursor<Folder>> mFolderListLoaderCallbacks = 4230e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy new LoaderCallbacks<ObjectCursor<Folder>>() { 4240e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 4250e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onLoaderReset(final Loader<ObjectCursor<Folder>> loader) { 4260e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 4270e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4280e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4290e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 4300e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onLoadFinished(final Loader<ObjectCursor<Folder>> loader, 4310e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final ObjectCursor<Folder> data) { 4320e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (data != null) { 4330e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // We need to keep track of all current folders in case one has been removed 4340e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final List<Integer> oldFolderIds = new ArrayList<Integer>(mFolderHolders.size()); 4350e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy for (int i = 0; i < mFolderHolders.size(); i++) { 4360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy oldFolderIds.add(mFolderHolders.keyAt(i)); 4370e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4380e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (data.moveToFirst()) { 4400e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy do { 4410e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Folder folder = data.getModel(); 4427614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah FolderHolder holder = mFolderHolders.get(folder.id); 4430e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4440e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (holder != null) { 4450e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Folder oldFolder = holder.getFolder(); 4460e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy holder.setFolder(folder); 4470e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4480e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /* 4490e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * We only need to change anything if the old Folder was null, or the 4500e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * unread count has changed. 4510e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 4520e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (oldFolder == null || oldFolder.unreadCount != folder.unreadCount) { 45342fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler populateUnreadSenders(holder, folder.unreadSenders); 4540e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy updateViews(holder); 4550e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4560e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } else { 4570e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Create the holder, and init a loader 4587614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah holder = createFolderHolder(folder.name); 4597614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah holder.setFolder(folder); 4607614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah mFolderHolders.put(folder.id, holder); 4610e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 462d85b965762c268418d1ef306e783c2f7bb0b3ddbPaul Sliwowski // We can not support displaying sender info with nested folders 463d85b965762c268418d1ef306e783c2f7bb0b3ddbPaul Sliwowski // because it doesn't scale. Disabling it for now, until we can 464d85b965762c268418d1ef306e783c2f7bb0b3ddbPaul Sliwowski // optimize it. 465d85b965762c268418d1ef306e783c2f7bb0b3ddbPaul Sliwowski // initFolderLoader(getLoaderId(folder.id)); 4667614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah populateUnreadSenders(holder, folder.unreadSenders); 4670e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4687614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah updateViews(holder); 4690e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4700e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mListUpdated = true; 4710e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4727614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah 4737614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah if (folder.hasChildren) { 4747614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah holder.getFolderIconImageView().setImageDrawable( 4757614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah getResources().getDrawable(R.drawable.ic_folder_parent_24dp)); 4767614bb95010ed42b7848b8dcc902fab5d6b84246Rohan Shah } 4770e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4780e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Note: #remove(int) removes from that POSITION 4790e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // #remove(Integer) removes that OBJECT 4800e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy oldFolderIds.remove(Integer.valueOf(folder.id)); 4810e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } while (data.moveToNext()); 4820e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4830e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 4844c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // Sort the folders by name 4854c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao // TODO(skennedy) recents? starred? 4864c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao final ImmutableSortedSet.Builder<FolderHolder> folderHoldersBuilder = 4874c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao new ImmutableSortedSet.Builder<FolderHolder>(FolderHolder.NAME_COMPARATOR); 4884c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao for (int i = 0; i < mFolderHolders.size(); i++) { 4894c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao folderHoldersBuilder.add(mFolderHolders.valueAt(i)); 4904c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao } 4914c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao mSortedFolderHolders = folderHoldersBuilder.build(); 4924c59495929c9b8a57fbcc05ad419a329240dbd00Jin Cao 4930e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy for (final int folderId : oldFolderIds) { 4940e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // We have a folder that no longer exists 4950e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mFolderHolders.remove(folderId); 4960e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mLoaderManager.destroyLoader(getLoaderId(folderId)); 4970e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mListUpdated = true; 4980e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 4990e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5000e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // If the list has not changed, we've already updated the counts, etc. 5010e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // If the list has changed, we need to rebuild it 5020e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (mListUpdated) { 5030e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mAdapter.notifyDataSetChanged(); 5040e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 5050e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } else { 5060e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy LogUtils.w(LOG_TAG, "Problem with folder list cursor returned from loader"); 5070e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 5080e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 5090e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5100e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private void initFolderLoader(final int loaderId) { 5110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy LogUtils.d(LOG_TAG, "Initializing folder loader %d", loaderId); 5120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy mLoaderManager.initLoader(loaderId, null, mFolderLoaderCallbacks); 5130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 5140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 5160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public Loader<ObjectCursor<Folder>> onCreateLoader(final int id, final Bundle args) { 5170e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final ObjectCursorLoader<Folder> loader = new ObjectCursorLoader<Folder>(getContext(), 51842fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler mFolderListUri, UIProvider.FOLDERS_PROJECTION_WITH_UNREAD_SENDERS, 51942fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler Folder.FACTORY); 5200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy loader.setUpdateThrottle(mFolderItemUpdateDelayMs); 5210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return loader; 5220e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 5230e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy }; 5240e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 52542fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler /** 52642fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler * This code is intended to roughly duplicate the FolderLoaderCallback's onLoadFinished 52742fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler */ 52842fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler private void populateUnreadSenders(final FolderHolder folderHolder, 52942fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler final String unreadSenders) { 53042fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler if (TextUtils.isEmpty(unreadSenders)) { 53142fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler folderHolder.setUnreadSenders(Collections.<String>emptyList()); 53242fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler return; 53342fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 53442fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler // Use a LinkedHashMap here to maintain ordering 53542fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler final Map<String, String> emailtoNameMap = Maps.newLinkedHashMap(); 53642fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler 53742fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler final Address[] senderAddresses = Address.parse(unreadSenders); 53842fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler 539a6e29eca5965025f2f788929834c01cc345d7670Andrew Sapperstein final BidiFormatter bidiFormatter = mAdapter.getBidiFormatter(); 54042fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler for (final Address senderAddress : senderAddresses) { 541821e578a71c7015646522e729600618f0ec16fc0Tony Mantler String sender = senderAddress.getPersonal(); 542a6e29eca5965025f2f788929834c01cc345d7670Andrew Sapperstein sender = (sender != null) ? bidiFormatter.unicodeWrap(sender) : null; 54342fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler final String senderEmail = senderAddress.getAddress(); 54442fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler 54542fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler if (!TextUtils.isEmpty(sender)) { 54642fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler final String existingSender = emailtoNameMap.get(senderEmail); 54742fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler if (!TextUtils.isEmpty(existingSender)) { 54842fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler // Prefer longer names 54942fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler if (existingSender.length() >= sender.length()) { 55042fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler // old name is longer 55142fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler sender = existingSender; 55242fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 55342fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 55442fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler emailtoNameMap.put(senderEmail, sender); 55542fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 55642fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler if (emailtoNameMap.size() >= 20) { 55742fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler break; 55842fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 55942fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 56042fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler 56142fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler final List<String> senders = Lists.newArrayList(emailtoNameMap.values()); 56242fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler folderHolder.setUnreadSenders(senders); 56342fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler } 56442fe486e9e80a13d7f94573af1000f883a5d9dabTony Mantler 5650e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy private final LoaderCallbacks<ObjectCursor<Conversation>> mFolderLoaderCallbacks = 5660e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy new LoaderCallbacks<ObjectCursor<Conversation>>() { 5670e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 5680e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onLoaderReset(final Loader<ObjectCursor<Conversation>> loader) { 5690e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Do nothing 5700e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 5710e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5720e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 5730e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public void onLoadFinished(final Loader<ObjectCursor<Conversation>> loader, 5740e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final ObjectCursor<Conversation> data) { 5750e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Sometimes names are condensed to just the first name. 5760e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // This data structure keeps a map of emails to names 5770e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Map<String, String> emailToNameMap = Maps.newHashMap(); 5780e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final List<String> senders = Lists.newArrayList(); 5790e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5800e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int folderId = getFolderId(loader.getId()); 5810e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5820e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final FolderHolder folderHolder = mFolderHolders.get(folderId); 5830e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int maxSenders = folderHolder.mFolder.unreadCount; 5840e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5850e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (maxSenders > 0 && data != null && data.moveToFirst()) { 5860e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy LogUtils.d(LOG_TAG, "Folder id %d loader finished", folderId); 5870e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5880e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Look through all conversations until we find 'maxSenders' unread 5890e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy int sendersFound = 0; 5900e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5910e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy do { 5920e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Conversation conversation = data.getModel(); 5930e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5940e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (!conversation.read) { 5950e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy String sender = null; 5960e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy String senderEmail = null; 5970e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy int priority = Integer.MIN_VALUE; 5980e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 5993b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux // Find the highest priority participant 6003b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux for (final ParticipantInfo p : 6013b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux conversation.conversationInfo.participantInfos) { 6023b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux if (sender == null || priority < p.priority) { 6033b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux sender = p.name; 6043b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux senderEmail = p.email; 6053b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux priority = p.priority; 6060e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6070e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6080e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 6090e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (sender != null) { 6100e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy sendersFound++; 6110e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final String existingSender = emailToNameMap.get(senderEmail); 6120e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (existingSender != null) { 6130e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // Prefer longer names 6140e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy if (existingSender.length() >= sender.length()) { 6150e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // old name is longer 6160e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy sender = existingSender; 6170e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } else { 6180e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy // new name is longer 6190e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy int index = senders.indexOf(existingSender); 6200e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy senders.set(index, sender); 6210e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6220e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } else { 6230e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy senders.add(sender); 6240e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6250e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy emailToNameMap.put(senderEmail, sender); 6260e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6270e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6280e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } while (data.moveToNext() && sendersFound < maxSenders); 6290e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } else { 6300e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy LogUtils.w(LOG_TAG, "Problem with folder cursor returned from loader"); 6310e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6320e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 6330e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy folderHolder.setUnreadSenders(senders); 6340e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 6350e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy /* 6360e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * Just update the views in place. We don't need to call notifyDataSetChanged() 6370e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy * because we aren't changing the teaser's visibility or position. 6380e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy */ 6390e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy updateViews(folderHolder); 6400e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6410e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy 6420e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy @Override 6430e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy public Loader<ObjectCursor<Conversation>> onCreateLoader(final int id, final Bundle args) { 6440e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final int folderId = getFolderId(id); 6450e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy final Uri uri = mFolderHolders.get(folderId).mFolder.conversationListUri 6460e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy .buildUpon() 6470e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy .appendQueryParameter(ConversationListQueryParameters.USE_NETWORK, 6480e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy Boolean.FALSE.toString()) 6490e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy .appendQueryParameter(ConversationListQueryParameters.LIMIT, MAX_SENDERS) 6500e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy .build(); 6510e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy return new ObjectCursorLoader<Conversation>(getContext(), uri, 6520e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy UIProvider.CONVERSATION_PROJECTION, Conversation.FACTORY); 6530e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy } 6540e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy }; 655fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy 656fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy @Override 657fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy public boolean commitLeaveBehindItem() { 658fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy // This view has no leave-behind 659fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy return false; 660fbf4f4729c9bea907cb57d4f449893eb2fc5dd1dScott Kennedy } 6610e8dc84326ad3e6d146a203538665f98dd98f688Scott Kennedy} 662