Disable search result if no contact detail to show.
Fixes: 147157426
Test: manually
Change-Id: I68f7a645fd22c3f4602ca46ed3047336949b84bb
diff --git a/res/layout/contact_result.xml b/res/layout/contact_result.xml
index f6188f7..d89b29f 100644
--- a/res/layout/contact_result.xml
+++ b/res/layout/contact_result.xml
@@ -39,6 +39,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.ContactResultTitle"
+ android:duplicateParentState="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0418d13..a8f1ab1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -150,6 +150,9 @@
" - Favorite"
</string>
+ <!-- Message in the add-to-favorite flow that no phone number available for this contact [CHAR_LIMIT=50] -->
+ <string name="no_phone_numbers">No phone numbers</string>
+
<!-- Heads Up Notification -->
<!-- Name of incoming call notification channel in app info [CHAR LIMIT=50] -->
<string name="in_call_notification_channel_name">Incoming call notification</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index af01627..a7c24a3 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -106,7 +106,9 @@
</style>
<!-- Contact results -->
- <style name="TextAppearance.ContactResultTitle" parent="TextAppearance.Body1"/>
+ <style name="TextAppearance.ContactResultTitle" parent="TextAppearance.Body1">
+ <item name="android:textColor">@color/primary_text_selector</item>
+ </style>
<!-- Add to favorite flow dialog -->
<style name="TextAppearance.AddFavoriteNumberTitle" parent="TextAppearance.Body1">
diff --git a/src/com/android/car/dialer/ui/common/DialerUtils.java b/src/com/android/car/dialer/ui/common/DialerUtils.java
index 3bcca38..01e6931 100644
--- a/src/com/android/car/dialer/ui/common/DialerUtils.java
+++ b/src/com/android/car/dialer/ui/common/DialerUtils.java
@@ -17,6 +17,10 @@
package com.android.car.dialer.ui.common;
import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.car.dialer.R;
import com.android.car.dialer.log.L;
@@ -106,4 +110,23 @@
L.w(TAG, "contact %s doesn't have any phone number", contact.getDisplayName());
}
}
+
+ /**
+ * Returns true if the contact has postal address and show postal address config is true.
+ */
+ private static boolean hasPostalAddress(Resources resources, @NonNull Contact contact) {
+ boolean showPostalAddress = resources.getBoolean(
+ R.bool.config_show_postal_address);
+ return showPostalAddress && (!contact.getPostalAddresses().isEmpty());
+ }
+
+ /**
+ * Returns true if the contact has either phone number or postal address to show.
+ */
+ public static boolean hasContactDetail(Resources resources, @Nullable Contact contact) {
+ boolean hasContactDetail = contact != null
+ && (!contact.getNumbers().isEmpty() || DialerUtils.hasPostalAddress(
+ resources, contact));
+ return hasContactDetail;
+ }
}
diff --git a/src/com/android/car/dialer/ui/contact/ContactListViewHolder.java b/src/com/android/car/dialer/ui/contact/ContactListViewHolder.java
index 8a35f87..9619151 100644
--- a/src/com/android/car/dialer/ui/contact/ContactListViewHolder.java
+++ b/src/com/android/car/dialer/ui/contact/ContactListViewHolder.java
@@ -126,8 +126,7 @@
return;
}
- boolean hasContactDetail = contact != null
- && (!contact.getNumbers().isEmpty() || hasPostalAddress(contact));
+ boolean hasContactDetail = DialerUtils.hasContactDetail(itemView.getResources(), contact);
ViewUtils.setEnabled(mShowContactDetailView, hasContactDetail);
ViewUtils.setVisible(mShowContactDetailView, hasContactDetail || forceShowButton);
@@ -140,12 +139,6 @@
}
}
- private boolean hasPostalAddress(@NonNull Contact contact) {
- boolean showPostalAddress = itemView.getResources().getBoolean(
- R.bool.config_show_postal_address);
- return showPostalAddress && (!contact.getPostalAddresses().isEmpty());
- }
-
/**
* Recycles views.
*/
diff --git a/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java b/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java
index 574cee0..6ddbad7 100644
--- a/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java
+++ b/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java
@@ -18,6 +18,7 @@
import android.app.AlertDialog;
import android.os.Bundle;
+import android.widget.Toast;
import androidx.lifecycle.ViewModelProviders;
@@ -89,7 +90,12 @@
return;
}
- mDialogAdapter.setPhoneNumbers(contact, contact.getNumbers());
- mCurrentDialog.show();
+ if (contact.getNumbers().isEmpty()) {
+ Toast.makeText(getContext(), R.string.no_phone_numbers, Toast.LENGTH_SHORT).show();
+ mCurrentDialog.dismiss();
+ } else {
+ mDialogAdapter.setPhoneNumbers(contact, contact.getNumbers());
+ mCurrentDialog.show();
+ }
}
}
diff --git a/src/com/android/car/dialer/ui/search/ContactResultViewHolder.java b/src/com/android/car/dialer/ui/search/ContactResultViewHolder.java
index ad1d139..3fd25b5 100644
--- a/src/com/android/car/dialer/ui/search/ContactResultViewHolder.java
+++ b/src/com/android/car/dialer/ui/search/ContactResultViewHolder.java
@@ -24,13 +24,16 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.car.dialer.R;
+import com.android.car.dialer.ui.common.DialerUtils;
import com.android.car.dialer.ui.view.ContactAvatarOutputlineProvider;
import com.android.car.telephony.common.Contact;
import com.android.car.telephony.common.TelecomUtils;
+import com.bumptech.glide.Glide;
+
/**
- * A {@link androidx.recyclerview.widget.RecyclerView.ViewHolder} that will parse relevant
- * views out of a {@code contact_result} layout.
+ * A {@link androidx.recyclerview.widget.RecyclerView.ViewHolder} that will parse relevant views out
+ * of a {@code contact_result} layout.
*/
public class ContactResultViewHolder extends RecyclerView.ViewHolder {
private final Context mContext;
@@ -54,11 +57,21 @@
* Populates the view that is represented by this ViewHolder with the information in the
* provided {@link Contact}.
*/
- public void bind(Contact contact) {
- mContactCard.setOnClickListener(
- v -> mOnShowContactDetailListener.onShowContactDetail(contact));
-
+ void bind(Contact contact) {
mContactName.setText(contact.getDisplayName());
TelecomUtils.setContactBitmapAsync(mContext, mContactPicture, contact);
+
+ if (DialerUtils.hasContactDetail(itemView.getResources(), contact)) {
+ mContactCard.setOnClickListener(
+ v -> mOnShowContactDetailListener.onShowContactDetail(contact));
+ } else {
+ itemView.setEnabled(false);
+ }
+ }
+
+ void recycle() {
+ itemView.setEnabled(true);
+ mContactCard.setOnClickListener(null);
+ Glide.with(mContext).clear(mContactPicture);
}
}
diff --git a/src/com/android/car/dialer/ui/search/ContactResultsAdapter.java b/src/com/android/car/dialer/ui/search/ContactResultsAdapter.java
index 7b1ac1f..2a6542d 100644
--- a/src/com/android/car/dialer/ui/search/ContactResultsAdapter.java
+++ b/src/com/android/car/dialer/ui/search/ContactResultsAdapter.java
@@ -77,6 +77,11 @@
}
@Override
+ public void onViewRecycled(ContactResultViewHolder holder) {
+ holder.recycle();
+ }
+
+ @Override
public int getItemViewType(int position) {
// Only one type of view is created, so no need for an individualized view type.
return 0;
diff --git a/src/com/android/car/dialer/ui/search/ContactResultsViewModel.java b/src/com/android/car/dialer/ui/search/ContactResultsViewModel.java
index 0607a30..eb15df8 100644
--- a/src/com/android/car/dialer/ui/search/ContactResultsViewModel.java
+++ b/src/com/android/car/dialer/ui/search/ContactResultsViewModel.java
@@ -171,8 +171,7 @@
public QueryParam getQueryParam() {
Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI,
Uri.encode(mSearchQueryLiveData.getValue()));
- return new QueryParam(lookupUri, CONTACT_DETAILS_PROJECTION,
- ContactsContract.Contacts.HAS_PHONE_NUMBER + "!=0",
+ return new QueryParam(lookupUri, CONTACT_DETAILS_PROJECTION, null,
/* selectionArgs= */null, /* orderBy= */null);
}
}
diff --git a/tests/robotests/src/com/android/car/dialer/ui/search/ContactResultsFragmentTest.java b/tests/robotests/src/com/android/car/dialer/ui/search/ContactResultsFragmentTest.java
index 83c8e79..7c2910e 100644
--- a/tests/robotests/src/com/android/car/dialer/ui/search/ContactResultsFragmentTest.java
+++ b/tests/robotests/src/com/android/car/dialer/ui/search/ContactResultsFragmentTest.java
@@ -37,6 +37,7 @@
import com.android.car.dialer.ui.contact.ContactDetailsViewModel;
import com.android.car.telephony.common.Contact;
import com.android.car.telephony.common.InMemoryPhoneBook;
+import com.android.car.telephony.common.PhoneNumber;
import com.android.car.ui.recyclerview.CarUiRecyclerView;
import org.junit.After;
@@ -50,6 +51,7 @@
import org.robolectric.annotation.Config;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
@Config(shadows = {ShadowAndroidViewModelFactory.class})
@@ -71,6 +73,8 @@
private Contact mMockContact;
@Mock
private Contact mContact1, mContact2, mContact3;
+ @Mock
+ private PhoneNumber mPhoneNumber;
@Before
public void setUp() {
@@ -84,8 +88,11 @@
ContactResultsViewModel.class, mMockContactResultsViewModel);
when(mContact1.getDisplayName()).thenReturn(DISPLAY_NAMES[0]);
+ when(mContact1.getNumbers()).thenReturn(Collections.singletonList(mPhoneNumber));
when(mContact2.getDisplayName()).thenReturn(DISPLAY_NAMES[1]);
+ when(mContact2.getNumbers()).thenReturn(Collections.singletonList(mPhoneNumber));
when(mContact3.getDisplayName()).thenReturn(DISPLAY_NAMES[2]);
+ when(mContact3.getNumbers()).thenReturn(Collections.singletonList(mPhoneNumber));
}
@After