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