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