1 /* 2 * Copyright (C) 2016 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.app.list; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.database.Cursor; 22 import android.telephony.PhoneNumberUtils; 23 import android.text.BidiFormatter; 24 import android.text.TextDirectionHeuristics; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import com.android.contacts.common.list.ContactListItemView; 28 import com.android.contacts.common.list.PhoneNumberListAdapter; 29 import com.android.contacts.common.util.ContactDisplayUtils; 30 import com.android.dialer.app.R; 31 import com.android.dialer.location.GeoUtil; 32 import com.android.dialer.util.CallUtil; 33 34 /** 35 * {@link PhoneNumberListAdapter} with the following added shortcuts, that are displayed as list 36 * items: 1) Directly calling the phone number query 2) Adding the phone number query to a contact 37 * 38 * <p>These shortcuts can be enabled or disabled to toggle whether or not they show up in the list. 39 */ 40 public class DialerPhoneNumberListAdapter extends PhoneNumberListAdapter { 41 42 public static final int SHORTCUT_INVALID = -1; 43 public static final int SHORTCUT_DIRECT_CALL = 0; 44 public static final int SHORTCUT_CREATE_NEW_CONTACT = 1; 45 public static final int SHORTCUT_ADD_TO_EXISTING_CONTACT = 2; 46 public static final int SHORTCUT_SEND_SMS_MESSAGE = 3; 47 public static final int SHORTCUT_MAKE_VIDEO_CALL = 4; 48 public static final int SHORTCUT_BLOCK_NUMBER = 5; 49 public static final int SHORTCUT_COUNT = 6; 50 51 private final boolean[] mShortcutEnabled = new boolean[SHORTCUT_COUNT]; 52 private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance(); 53 private final boolean mVideoCallingEnabled; 54 private final String mCountryIso; 55 56 private String mFormattedQueryString; 57 DialerPhoneNumberListAdapter(Context context)58 public DialerPhoneNumberListAdapter(Context context) { 59 super(context); 60 61 mCountryIso = GeoUtil.getCurrentCountryIso(context); 62 mVideoCallingEnabled = CallUtil.isVideoEnabled(context); 63 } 64 65 @Override getCount()66 public int getCount() { 67 return super.getCount() + getShortcutCount(); 68 } 69 70 /** @return The number of enabled shortcuts. Ranges from 0 to a maximum of SHORTCUT_COUNT */ getShortcutCount()71 public int getShortcutCount() { 72 int count = 0; 73 for (int i = 0; i < mShortcutEnabled.length; i++) { 74 if (mShortcutEnabled[i]) { 75 count++; 76 } 77 } 78 return count; 79 } 80 disableAllShortcuts()81 public void disableAllShortcuts() { 82 for (int i = 0; i < mShortcutEnabled.length; i++) { 83 mShortcutEnabled[i] = false; 84 } 85 } 86 87 @Override getItemViewType(int position)88 public int getItemViewType(int position) { 89 final int shortcut = getShortcutTypeFromPosition(position); 90 if (shortcut >= 0) { 91 // shortcutPos should always range from 1 to SHORTCUT_COUNT 92 return super.getViewTypeCount() + shortcut; 93 } else { 94 return super.getItemViewType(position); 95 } 96 } 97 98 @Override getViewTypeCount()99 public int getViewTypeCount() { 100 // Number of item view types in the super implementation + 2 for the 2 new shortcuts 101 return super.getViewTypeCount() + SHORTCUT_COUNT; 102 } 103 104 @Override getView(int position, View convertView, ViewGroup parent)105 public View getView(int position, View convertView, ViewGroup parent) { 106 final int shortcutType = getShortcutTypeFromPosition(position); 107 if (shortcutType >= 0) { 108 if (convertView != null) { 109 assignShortcutToView((ContactListItemView) convertView, shortcutType); 110 return convertView; 111 } else { 112 final ContactListItemView v = 113 new ContactListItemView( 114 getContext(), null, mVideoCallingEnabled, isCallAndShareEnabled()); 115 assignShortcutToView(v, shortcutType); 116 return v; 117 } 118 } else { 119 return super.getView(position, convertView, parent); 120 } 121 } 122 123 @Override newView( Context context, int partition, Cursor cursor, int position, ViewGroup parent)124 protected ContactListItemView newView( 125 Context context, int partition, Cursor cursor, int position, ViewGroup parent) { 126 final ContactListItemView view = super.newView(context, partition, cursor, position, parent); 127 128 view.setSupportVideoCallIcon(mVideoCallingEnabled); 129 view.setSupportCallAndShareIcon(isCallAndShareEnabled()); 130 return view; 131 } 132 133 /** 134 * @param position The position of the item 135 * @return The enabled shortcut type matching the given position if the item is a shortcut, -1 136 * otherwise 137 */ getShortcutTypeFromPosition(int position)138 public int getShortcutTypeFromPosition(int position) { 139 int shortcutCount = position - super.getCount(); 140 if (shortcutCount >= 0) { 141 // Iterate through the array of shortcuts, looking only for shortcuts where 142 // mShortcutEnabled[i] is true 143 for (int i = 0; shortcutCount >= 0 && i < mShortcutEnabled.length; i++) { 144 if (mShortcutEnabled[i]) { 145 shortcutCount--; 146 if (shortcutCount < 0) { 147 return i; 148 } 149 } 150 } 151 throw new IllegalArgumentException( 152 "Invalid position - greater than cursor count " + " but not a shortcut."); 153 } 154 return SHORTCUT_INVALID; 155 } 156 157 @Override isEmpty()158 public boolean isEmpty() { 159 return getShortcutCount() == 0 && super.isEmpty(); 160 } 161 162 @Override isEnabled(int position)163 public boolean isEnabled(int position) { 164 final int shortcutType = getShortcutTypeFromPosition(position); 165 if (shortcutType >= 0) { 166 return true; 167 } else { 168 return super.isEnabled(position); 169 } 170 } 171 assignShortcutToView(ContactListItemView v, int shortcutType)172 private void assignShortcutToView(ContactListItemView v, int shortcutType) { 173 final CharSequence text; 174 final int drawableId; 175 final Resources resources = getContext().getResources(); 176 final String number = getFormattedQueryString(); 177 switch (shortcutType) { 178 case SHORTCUT_DIRECT_CALL: 179 text = 180 ContactDisplayUtils.getTtsSpannedPhoneNumber( 181 resources, 182 R.string.search_shortcut_call_number, 183 mBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR)); 184 drawableId = R.drawable.ic_search_phone; 185 break; 186 case SHORTCUT_CREATE_NEW_CONTACT: 187 text = resources.getString(R.string.search_shortcut_create_new_contact); 188 drawableId = R.drawable.ic_search_add_contact; 189 break; 190 case SHORTCUT_ADD_TO_EXISTING_CONTACT: 191 text = resources.getString(R.string.search_shortcut_add_to_contact); 192 drawableId = R.drawable.quantum_ic_person_white_24; 193 break; 194 case SHORTCUT_SEND_SMS_MESSAGE: 195 text = resources.getString(R.string.search_shortcut_send_sms_message); 196 drawableId = R.drawable.quantum_ic_message_white_24; 197 break; 198 case SHORTCUT_MAKE_VIDEO_CALL: 199 text = resources.getString(R.string.search_shortcut_make_video_call); 200 drawableId = R.drawable.quantum_ic_videocam_white_24; 201 break; 202 case SHORTCUT_BLOCK_NUMBER: 203 text = resources.getString(R.string.search_shortcut_block_number); 204 drawableId = R.drawable.ic_not_interested_googblue_24dp; 205 break; 206 default: 207 throw new IllegalArgumentException("Invalid shortcut type"); 208 } 209 v.setDrawableResource(drawableId); 210 v.setDisplayName(text); 211 v.setPhotoPosition(super.getPhotoPosition()); 212 v.setAdjustSelectionBoundsEnabled(false); 213 } 214 215 /** @return True if the shortcut state (disabled vs enabled) was changed by this operation */ setShortcutEnabled(int shortcutType, boolean visible)216 public boolean setShortcutEnabled(int shortcutType, boolean visible) { 217 final boolean changed = mShortcutEnabled[shortcutType] != visible; 218 mShortcutEnabled[shortcutType] = visible; 219 return changed; 220 } 221 getFormattedQueryString()222 public String getFormattedQueryString() { 223 return mFormattedQueryString; 224 } 225 226 @Override setQueryString(String queryString)227 public void setQueryString(String queryString) { 228 mFormattedQueryString = 229 PhoneNumberUtils.formatNumber(PhoneNumberUtils.normalizeNumber(queryString), mCountryIso); 230 super.setQueryString(queryString); 231 } 232 } 233