1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.searchfragment.directories; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.database.Cursor; 22 import android.net.Uri; 23 import android.provider.ContactsContract; 24 import android.provider.ContactsContract.CommonDataKinds.Phone; 25 import android.provider.ContactsContract.Contacts; 26 import android.support.v7.widget.RecyclerView; 27 import android.text.TextUtils; 28 import android.view.View; 29 import android.widget.ImageView; 30 import android.widget.QuickContactBadge; 31 import android.widget.TextView; 32 import com.android.dialer.callintent.CallInitiationType; 33 import com.android.dialer.callintent.CallIntentBuilder; 34 import com.android.dialer.common.cp2.DirectoryCompat; 35 import com.android.dialer.contactphoto.ContactPhotoManager; 36 import com.android.dialer.lettertile.LetterTileDrawable; 37 import com.android.dialer.precall.PreCall; 38 import com.android.dialer.searchfragment.common.Projections; 39 import com.android.dialer.searchfragment.common.QueryBoldingUtil; 40 import com.android.dialer.searchfragment.common.R; 41 import com.android.dialer.searchfragment.common.SearchCursor; 42 43 /** ViewHolder for a directory contact row. */ 44 public final class DirectoryContactViewHolder extends RecyclerView.ViewHolder 45 implements View.OnClickListener { 46 47 private final Context context; 48 private final TextView nameView; 49 private final TextView numberView; 50 private final QuickContactBadge photo; 51 private final ImageView workBadge; 52 53 private String number; 54 55 public DirectoryContactViewHolder(View view) { 56 super(view); 57 view.setOnClickListener(this); 58 photo = view.findViewById(R.id.photo); 59 nameView = view.findViewById(R.id.primary); 60 numberView = view.findViewById(R.id.secondary); 61 workBadge = view.findViewById(R.id.work_icon); 62 context = view.getContext(); 63 } 64 65 /** 66 * Binds the ViewHolder with a cursor from {@link DirectoryContactsCursorLoader} with the data 67 * found at the cursors current position. 68 */ 69 public void bind(SearchCursor cursor, String query) { 70 number = cursor.getString(Projections.PHONE_NUMBER); 71 String name = cursor.getString(Projections.DISPLAY_NAME); 72 String label = getLabel(context.getResources(), cursor); 73 String secondaryInfo = 74 TextUtils.isEmpty(label) 75 ? number 76 : context.getString(R.string.call_subject_type_and_number, label, number); 77 78 nameView.setText(QueryBoldingUtil.getNameWithQueryBolded(query, name, context)); 79 numberView.setText(QueryBoldingUtil.getNameWithQueryBolded(query, secondaryInfo, context)); 80 workBadge.setVisibility( 81 DirectoryCompat.isOnlyEnterpriseDirectoryId(cursor.getDirectoryId()) 82 ? View.VISIBLE 83 : View.GONE); 84 85 if (shouldShowPhoto(cursor)) { 86 nameView.setVisibility(View.VISIBLE); 87 photo.setVisibility(View.VISIBLE); 88 String photoUri = cursor.getString(Projections.PHOTO_URI); 89 ContactPhotoManager.getInstance(context) 90 .loadDialerThumbnailOrPhoto( 91 photo, 92 getContactUri(cursor), 93 cursor.getLong(Projections.PHOTO_ID), 94 photoUri == null ? null : Uri.parse(photoUri), 95 name, 96 LetterTileDrawable.TYPE_DEFAULT); 97 } else { 98 nameView.setVisibility(View.GONE); 99 photo.setVisibility(View.INVISIBLE); 100 } 101 } 102 103 // Show the contact photo next to only the first number if a contact has multiple numbers 104 private boolean shouldShowPhoto(SearchCursor cursor) { 105 int currentPosition = cursor.getPosition(); 106 String currentLookupKey = cursor.getString(Projections.LOOKUP_KEY); 107 cursor.moveToPosition(currentPosition - 1); 108 109 if (!cursor.isHeader() && !cursor.isBeforeFirst()) { 110 String previousLookupKey = cursor.getString(Projections.LOOKUP_KEY); 111 cursor.moveToPosition(currentPosition); 112 return !currentLookupKey.equals(previousLookupKey); 113 } 114 cursor.moveToPosition(currentPosition); 115 return true; 116 } 117 118 // TODO(calderwoodra): unify this into a utility method with CallLogAdapter#getNumberType 119 private static String getLabel(Resources resources, Cursor cursor) { 120 int numberType = cursor.getInt(Projections.PHONE_TYPE); 121 String numberLabel = cursor.getString(Projections.PHONE_LABEL); 122 123 // Returns empty label instead of "custom" if the custom label is empty. 124 if (numberType == Phone.TYPE_CUSTOM && TextUtils.isEmpty(numberLabel)) { 125 return ""; 126 } 127 return (String) Phone.getTypeLabel(resources, numberType, numberLabel); 128 } 129 130 private static Uri getContactUri(SearchCursor cursor) { 131 long contactId = cursor.getLong(Projections.ID); 132 String lookupKey = cursor.getString(Projections.LOOKUP_KEY); 133 return Contacts.getLookupUri(contactId, lookupKey) 134 .buildUpon() 135 .appendQueryParameter( 136 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(cursor.getDirectoryId())) 137 .build(); 138 } 139 140 @Override 141 public void onClick(View v) { 142 PreCall.start(context, new CallIntentBuilder(number, CallInitiationType.Type.REGULAR_SEARCH)); 143 } 144 } 145