1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/*
2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project
3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License");
5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License.
6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at
7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *      http://www.apache.org/licenses/LICENSE-2.0
9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software
11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS,
12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and
14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License.
15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui.conversationlist;
17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.app.Activity;
19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.app.Fragment;
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor;
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Rect;
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri;
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Bundle;
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.Parcelable;
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.view.ViewCompat;
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.view.ViewGroupCompat;
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v7.widget.LinearLayoutManager;
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v7.widget.RecyclerView;
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.LayoutInflater;
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.Menu;
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.MenuInflater;
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.MenuItem;
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.View;
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.View.OnClickListener;
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.ViewGroup;
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.ViewGroup.MarginLayoutParams;
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.ViewPropertyAnimator;
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.accessibility.AccessibilityManager;
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.AbsListView;
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.ImageView;
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.R;
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.annotation.VisibleForAnimation;
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel;
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.binding.Binding;
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.binding.BindingBase;
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ConversationListData;
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ConversationListData.ConversationListDataListener;
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ConversationListItemData;
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.BugleAnimationTags;
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.ListEmptyView;
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.SnackBarInteraction;
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.UIIntents;
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.AccessibilityUtil;
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert;
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ImeUtil;
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil;
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.UiUtils;
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.annotations.VisibleForTesting;
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.ArrayList;
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List;
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/**
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Shows a list of conversations.
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ConversationListFragment extends Fragment implements ConversationListDataListener,
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        ConversationListItemView.HostInterface {
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String BUNDLE_ARCHIVED_MODE = "archived_mode";
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String BUNDLE_FORWARD_MESSAGE_MODE = "forward_message_mode";
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final boolean VERBOSE = false;
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private MenuItem mShowBlockedMenuItem;
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private boolean mArchiveMode;
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private boolean mBlockedAvailable;
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private boolean mForwardMessageMode;
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public interface ConversationListFragmentHost {
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public void onConversationClick(final ConversationListData listData,
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                        final ConversationListItemData conversationListItemData,
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                        final boolean isLongClick,
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                        final ConversationListItemView conversationView);
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public void onCreateConversationClick();
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public boolean isConversationSelected(final String conversationId);
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public boolean isSwipeAnimatable();
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public boolean isSelectionMode();
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public boolean hasWindowFocus();
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ConversationListFragmentHost mHost;
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private RecyclerView mRecyclerView;
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ImageView mStartNewConversationButton;
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ListEmptyView mEmptyListMessageView;
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ConversationListAdapter mAdapter;
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // Saved Instance State Data - only for temporal data which is nice to maintain but not
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // critical for correctness.
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY =
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            "conversationListViewState";
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private Parcelable mListState;
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @VisibleForTesting
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    final Binding<ConversationListData> mListBinding = BindingBase.createBinding(this);
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static ConversationListFragment createArchivedConversationListFragment() {
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return createConversationListFragment(BUNDLE_ARCHIVED_MODE);
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static ConversationListFragment createForwardMessageConversationListFragment() {
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return createConversationListFragment(BUNDLE_FORWARD_MESSAGE_MODE);
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static ConversationListFragment createConversationListFragment(String modeKeyName) {
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ConversationListFragment fragment = new ConversationListFragment();
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Bundle bundle = new Bundle();
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        bundle.putBoolean(modeKeyName, true);
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        fragment.setArguments(bundle);
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return fragment;
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * {@inheritDoc} from Fragment
124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onCreate(final Bundle bundle) {
127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onCreate(bundle);
128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mListBinding.getData().init(getLoaderManager(), mListBinding);
129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mAdapter = new ConversationListAdapter(getActivity(), null, this);
130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onResume() {
134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onResume();
135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.notNull(mHost);
137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setScrolledToNewestConversationIfNeeded();
138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        updateUi();
140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void setScrolledToNewestConversationIfNeeded() {
143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!mArchiveMode
144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                && !mForwardMessageMode
145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                && isScrolledToFirstConversation()
146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                && mHost.hasWindowFocus()) {
147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mListBinding.getData().setScrolledToNewestConversation(true);
148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private boolean isScrolledToFirstConversation() {
152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        int firstItemPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                .findFirstCompletelyVisibleItemPosition();
154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return firstItemPosition == 0;
155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * {@inheritDoc} from Fragment
159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onDestroy() {
162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onDestroy();
163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mListBinding.unbind();
164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mHost = null;
165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * {@inheritDoc} from Fragment
169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Bundle savedInstanceState) {
173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.conversation_list_fragment,
174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                container, false);
175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mRecyclerView = (RecyclerView) rootView.findViewById(android.R.id.list);
176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mEmptyListMessageView = (ListEmptyView) rootView.findViewById(R.id.no_conversations_view);
177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mEmptyListMessageView.setImageHint(R.drawable.ic_oobe_conv_list);
178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // The default behavior for default layout param generation by LinearLayoutManager is to
179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // provide width and height of WRAP_CONTENT, but this is not desirable for
180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // ConversationListFragment; the view in each row should be a width of MATCH_PARENT so that
181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // the entire row is tappable.
182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Activity activity = getActivity();
183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final LinearLayoutManager manager = new LinearLayoutManager(activity) {
184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public RecyclerView.LayoutParams generateDefaultLayoutParams() {
186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        ViewGroup.LayoutParams.WRAP_CONTENT);
188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        };
190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mRecyclerView.setLayoutManager(manager);
191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mRecyclerView.setHasFixedSize(true);
192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mRecyclerView.setAdapter(mAdapter);
193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            int mCurrentState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (mCurrentState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        || mCurrentState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    ImeUtil.get().hideImeKeyboard(getActivity(), mRecyclerView);
201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (isScrolledToFirstConversation()) {
204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    setScrolledToNewestConversationIfNeeded();
205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                } else {
206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    mListBinding.getData().setScrolledToNewestConversation(false);
207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public void onScrollStateChanged(final RecyclerView recyclerView, final int newState) {
212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                mCurrentState = newState;
213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        });
215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mRecyclerView.addOnItemTouchListener(new ConversationListSwipeHelper(mRecyclerView));
216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (savedInstanceState != null) {
218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mListState = savedInstanceState.getParcelable(SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY);
219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mStartNewConversationButton = (ImageView) rootView.findViewById(
222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                R.id.start_new_conversation_button);
223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mArchiveMode) {
224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mStartNewConversationButton.setVisibility(View.GONE);
225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mStartNewConversationButton.setVisibility(View.VISIBLE);
227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mStartNewConversationButton.setOnClickListener(new OnClickListener() {
228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                @Override
229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                public void onClick(final View clickView) {
230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    mHost.onCreateConversationClick();
231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            });
233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        ViewCompat.setTransitionName(mStartNewConversationButton, BugleAnimationTags.TAG_FABICON);
235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // The root view has a non-null background, which by default is deemed by the framework
237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // to be a "transition group," where all child views are animated together during an
238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // activity transition. However, we want each individual items in the recycler view to
239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // show explode animation themselves, so we explicitly tag the root view to be a non-group.
240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        ViewGroupCompat.setTransitionGroup(rootView, false);
241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setHasOptionsMenu(true);
243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return rootView;
244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onAttach(final Activity activity) {
248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onAttach(activity);
249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (VERBOSE) {
250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            LogUtil.v(LogUtil.BUGLE_TAG, "Attaching List");
251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Bundle arguments = getArguments();
253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (arguments != null) {
254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mArchiveMode = arguments.getBoolean(BUNDLE_ARCHIVED_MODE, false);
255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mForwardMessageMode = arguments.getBoolean(BUNDLE_FORWARD_MESSAGE_MODE, false);
256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mListBinding.bind(DataModel.get().createConversationListData(activity, this, mArchiveMode));
258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onSaveInstanceState(final Bundle outState) {
263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onSaveInstanceState(outState);
264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mListState != null) {
265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            outState.putParcelable(SAVED_INSTANCE_STATE_LIST_VIEW_STATE_KEY, mListState);
266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onPause() {
271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onPause();
272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mListState = mRecyclerView.getLayoutManager().onSaveInstanceState();
273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mListBinding.getData().setScrolledToNewestConversation(false);
274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Call this immediately after attaching the fragment
278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void setHost(final ConversationListFragmentHost host) {
280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.isNull(mHost);
281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mHost = host;
282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onConversationListCursorUpdated(final ConversationListData data,
286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Cursor cursor) {
287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mListBinding.ensureBound(data);
288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Cursor oldCursor = mAdapter.swapCursor(cursor);
289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        updateEmptyListUi(cursor == null || cursor.getCount() == 0);
290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mListState != null && cursor != null && oldCursor == null) {
291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);
292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void setBlockedParticipantsAvailable(final boolean blockedAvailable) {
297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mBlockedAvailable = blockedAvailable;
298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mShowBlockedMenuItem != null) {
299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mShowBlockedMenuItem.setVisible(blockedAvailable);
300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void updateUi() {
304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mAdapter.notifyDataSetChanged();
305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onPrepareOptionsMenu(final Menu menu) {
309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onPrepareOptionsMenu(menu);
310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final MenuItem startNewConversationMenuItem =
311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                menu.findItem(R.id.action_start_new_conversation);
312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (startNewConversationMenuItem != null) {
313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // It is recommended for the Floating Action button functionality to be duplicated as a
314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // menu
315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            AccessibilityManager accessibilityManager = (AccessibilityManager)
316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE);
317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            startNewConversationMenuItem.setVisible(accessibilityManager
318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    .isTouchExplorationEnabled());
319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final MenuItem archive = menu.findItem(R.id.action_show_archived);
322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (archive != null) {
323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            archive.setVisible(true);
324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!isAdded()) {
330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Guard against being called before we're added to the activity
331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return;
332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mShowBlockedMenuItem = menu.findItem(R.id.action_show_blocked_contacts);
335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mShowBlockedMenuItem != null) {
336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mShowBlockedMenuItem.setVisible(mBlockedAvailable);
337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * {@inheritDoc} from ConversationListItemView.HostInterface
342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void onConversationClicked(final ConversationListItemData conversationListItemData,
345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final boolean isLongClick, final ConversationListItemView conversationView) {
346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ConversationListData listData = mListBinding.getData();
347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mHost.onConversationClick(listData, conversationListItemData, isLongClick,
348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                conversationView);
349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * {@inheritDoc} from ConversationListItemView.HostInterface
353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public boolean isConversationSelected(final String conversationId) {
356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return mHost.isConversationSelected(conversationId);
357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public boolean isSwipeAnimatable() {
361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return mHost.isSwipeAnimatable();
362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // Show and hide empty list UI as needed with appropriate text based on view specifics
365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void updateEmptyListUi(final boolean isEmpty) {
366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (isEmpty) {
367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            int emptyListText;
368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (!mListBinding.getData().getHasFirstSyncCompleted()) {
369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                emptyListText = R.string.conversation_list_first_sync_text;
370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else if (mArchiveMode) {
371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                emptyListText = R.string.archived_conversation_list_empty_text;
372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                emptyListText = R.string.conversation_list_empty_text;
374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mEmptyListMessageView.setTextHint(emptyListText);
376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mEmptyListMessageView.setVisibility(View.VISIBLE);
377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mEmptyListMessageView.setIsImageVisible(true);
378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mEmptyListMessageView.setIsVerticallyCentered(true);
379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mEmptyListMessageView.setVisibility(View.GONE);
381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
382d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
383d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public List<SnackBarInteraction> getSnackBarInteractions() {
386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final List<SnackBarInteraction> interactions = new ArrayList<SnackBarInteraction>(1);
387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final SnackBarInteraction fabInteraction =
388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                new SnackBarInteraction.BasicSnackBarInteraction(mStartNewConversationButton);
389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        interactions.add(fabInteraction);
390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return interactions;
391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ViewPropertyAnimator getNormalizedFabAnimator() {
394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return mStartNewConversationButton.animate()
395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                .setInterpolator(UiUtils.DEFAULT_INTERPOLATOR)
396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                .setDuration(getActivity().getResources().getInteger(
397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        R.integer.fab_animation_duration_ms));
398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public ViewPropertyAnimator dismissFab() {
401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // To prevent clicking while animating.
402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mStartNewConversationButton.setEnabled(false);
403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final MarginLayoutParams lp =
404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                (MarginLayoutParams) mStartNewConversationButton.getLayoutParams();
405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final float fabWidthWithLeftRightMargin = mStartNewConversationButton.getWidth()
406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                + lp.leftMargin + lp.rightMargin;
407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int direction = AccessibilityUtil.isLayoutRtl(mStartNewConversationButton) ? -1 : 1;
408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return getNormalizedFabAnimator().translationX(direction * fabWidthWithLeftRightMargin);
409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public ViewPropertyAnimator showFab() {
412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return getNormalizedFabAnimator().translationX(0).withEndAction(new Runnable() {
413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public void run() {
415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Re-enable clicks after the animation.
416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                mStartNewConversationButton.setEnabled(true);
417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        });
419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public View getHeroElementForTransition() {
422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return mArchiveMode ? null : mStartNewConversationButton;
423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @VisibleForAnimation
426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public RecyclerView getRecyclerView() {
427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return mRecyclerView;
428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void startFullScreenPhotoViewer(
432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final Uri initialPhoto, final Rect initialPhotoBounds, final Uri photosUri) {
433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        UIIntents.get().launchFullScreenPhotoViewer(
434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                getActivity(), initialPhoto, initialPhotoBounds, photosUri);
435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void startFullScreenVideoViewer(final Uri videoUri) {
439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        UIIntents.get().launchFullScreenVideoViewer(getActivity(), videoUri);
440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public boolean isSelectionMode() {
444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return mHost != null && mHost.isSelectionMode();
445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
447