blob: 1681097bfdaea43bc65285e211c90e8c053500fd [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.dialer.searchfragment.list;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.common.Assert;
import com.android.dialer.searchfragment.common.RowClickListener;
import com.android.dialer.searchfragment.common.SearchCursor;
import com.android.dialer.searchfragment.cp2.SearchContactViewHolder;
import com.android.dialer.searchfragment.list.SearchCursorManager.RowType;
import com.android.dialer.searchfragment.nearbyplaces.NearbyPlaceViewHolder;
import com.android.dialer.searchfragment.remote.RemoteContactViewHolder;
import java.util.List;
/** RecyclerView adapter for {@link NewSearchFragment}. */
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public final class SearchAdapter extends RecyclerView.Adapter<ViewHolder> {
private final SearchCursorManager searchCursorManager;
private final Context context;
private boolean showZeroSuggest;
private String query;
// Raw query number from dialpad, which may contain special character such as "+". This is used
// for actions to add contact or send sms.
private String rawNumber;
private CallInitiationType.Type callInitiationType;
private OnClickListener allowClickListener;
private OnClickListener dismissClickListener;
private RowClickListener rowClickListener;
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public SearchAdapter(
Context context, SearchCursorManager searchCursorManager, RowClickListener rowClickListener) {
this.context = context;
this.searchCursorManager = searchCursorManager;
this.rowClickListener = rowClickListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup root, @RowType int rowType) {
switch (rowType) {
case RowType.CONTACT_ROW:
return new SearchContactViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false),
rowClickListener);
case RowType.NEARBY_PLACES_ROW:
return new NearbyPlaceViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false));
case RowType.CONTACT_HEADER:
case RowType.DIRECTORY_HEADER:
case RowType.NEARBY_PLACES_HEADER:
return new HeaderViewHolder(
LayoutInflater.from(context).inflate(R.layout.header_layout, root, false));
case RowType.DIRECTORY_ROW:
return new RemoteContactViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false));
case RowType.SEARCH_ACTION:
return new SearchActionViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_action_layout, root, false));
case RowType.LOCATION_REQUEST:
return new LocationPermissionViewHolder(
LayoutInflater.from(context).inflate(R.layout.location_permission_row, root, false),
allowClickListener,
dismissClickListener);
case RowType.INVALID:
default:
throw Assert.createIllegalStateFailException("Invalid RowType: " + rowType);
}
}
@Override
public @RowType int getItemViewType(int position) {
return searchCursorManager.getRowType(position);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder instanceof SearchContactViewHolder) {
((SearchContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof NearbyPlaceViewHolder) {
((NearbyPlaceViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof RemoteContactViewHolder) {
((RemoteContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof HeaderViewHolder) {
String header =
searchCursorManager.getCursor(position).getString(SearchCursor.HEADER_TEXT_POSITION);
((HeaderViewHolder) holder).setHeader(header);
} else if (holder instanceof SearchActionViewHolder) {
((SearchActionViewHolder) holder)
.setAction(
searchCursorManager.getSearchAction(position),
position,
TextUtils.isEmpty(rawNumber) ? query : rawNumber,
callInitiationType);
} else if (holder instanceof LocationPermissionViewHolder) {
// No-op
} else {
throw Assert.createIllegalStateFailException("Invalid ViewHolder: " + holder);
}
}
public void setContactsCursor(SearchCursor cursor) {
if (searchCursorManager.setContactsCursor(cursor)) {
// Since this is a new contacts cursor, we need to reapply the filter.
searchCursorManager.setQuery(query);
notifyDataSetChanged();
}
}
void clear() {
searchCursorManager.clear();
}
@Override
public int getItemCount() {
if (TextUtils.isEmpty(query) && !showZeroSuggest) {
return 0;
}
return searchCursorManager.getCount();
}
/**
* @param visible If true and query is empty, the adapter won't show any list elements.
* @see #setQuery(String, String, CallInitiationType.Type)
* @see #getItemCount()
*/
public void setZeroSuggestVisible(boolean visible) {
showZeroSuggest = visible;
}
public void setQuery(String query, @Nullable String rawNumber, CallInitiationType.Type type) {
this.query = query;
this.rawNumber = rawNumber;
this.callInitiationType = type;
if (searchCursorManager.setQuery(query)) {
notifyDataSetChanged();
}
}
/** Sets the actions to be shown at the bottom of the search results. */
void setSearchActions(List<Integer> actions) {
if (searchCursorManager.setSearchActions(actions)) {
notifyDataSetChanged();
}
}
public void setNearbyPlacesCursor(SearchCursor nearbyPlacesCursor) {
if (searchCursorManager.setNearbyPlacesCursor(nearbyPlacesCursor)) {
notifyDataSetChanged();
}
}
/**
* Updates the adapter to show the location request row element. If the element was previously
* hidden, the adapter will call {@link #notifyDataSetChanged()}.
*/
public void showLocationPermissionRequest(
OnClickListener allowClickListener, OnClickListener dismissClickListener) {
this.allowClickListener = Assert.isNotNull(allowClickListener);
this.dismissClickListener = Assert.isNotNull(dismissClickListener);
if (searchCursorManager.showLocationPermissionRequest(true)) {
notifyItemInserted(0);
}
}
/**
* Updates the adapter to hide the location request row element. If the element was previously
* visible, the adapter will call {@link #notifyDataSetChanged()}.
*/
void hideLocationPermissionRequest() {
allowClickListener = null;
dismissClickListener = null;
if (searchCursorManager.showLocationPermissionRequest(false)) {
notifyItemRemoved(0);
}
}
public void setRemoteContactsCursor(SearchCursor remoteContactsCursor) {
if (searchCursorManager.setCorpDirectoryCursor(remoteContactsCursor)) {
notifyDataSetChanged();
}
}
/** Viewholder for R.layout.location_permission_row that requests the location permission. */
private static class LocationPermissionViewHolder extends RecyclerView.ViewHolder {
LocationPermissionViewHolder(
View itemView, OnClickListener allowClickListener, OnClickListener dismissClickListener) {
super(itemView);
Assert.isNotNull(allowClickListener);
Assert.isNotNull(dismissClickListener);
itemView
.findViewById(
com.android.dialer.searchfragment.nearbyplaces.R.id.location_permission_allow)
.setOnClickListener(allowClickListener);
itemView
.findViewById(
com.android.dialer.searchfragment.nearbyplaces.R.id.location_permission_dismiss)
.setOnClickListener(dismissClickListener);
}
}
}