1 /*
2  * Copyright (C) 2012 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.contacts.util;
18 
19 import static android.provider.ContactsContract.CommonDataKinds.Phone;
20 
21 import android.content.res.Resources;
22 import android.text.Spannable;
23 import android.text.SpannableString;
24 import android.text.TextUtils;
25 import android.text.style.TtsSpan;
26 import android.util.Patterns;
27 import androidx.annotation.Nullable;
28 import com.android.contacts.R;
29 import com.android.contacts.compat.PhoneNumberUtilsCompat;
30 import com.android.contacts.preference.ContactsPreferences;
31 
32 /**
33  * Methods for handling various contact data labels.
34  */
35 public class ContactDisplayUtils {
36 
37     private static final String TAG = ContactDisplayUtils.class.getSimpleName();
38 
39     /**
40      * Checks if the given data type is a custom type.
41      *
42      * @param type Phone data type.
43      * @return {@literal true} if the type is custom.  {@literal false} if not.
44      */
isCustomPhoneType(Integer type)45     public static boolean isCustomPhoneType(Integer type) {
46         return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
47     }
48 
49     /**
50      * Find a label for calling.
51      *
52      * @param type The type of number.
53      * @return An appropriate string label.
54      */
getPhoneLabelResourceId(Integer type)55     public static int getPhoneLabelResourceId(Integer type) {
56         if (type == null) return R.string.call_other;
57         switch (type) {
58             case Phone.TYPE_HOME:
59                 return R.string.call_home;
60             case Phone.TYPE_MOBILE:
61                 return R.string.call_mobile;
62             case Phone.TYPE_WORK:
63                 return R.string.call_work;
64             case Phone.TYPE_FAX_WORK:
65                 return R.string.call_fax_work;
66             case Phone.TYPE_FAX_HOME:
67                 return R.string.call_fax_home;
68             case Phone.TYPE_PAGER:
69                 return R.string.call_pager;
70             case Phone.TYPE_OTHER:
71                 return R.string.call_other;
72             case Phone.TYPE_CALLBACK:
73                 return R.string.call_callback;
74             case Phone.TYPE_CAR:
75                 return R.string.call_car;
76             case Phone.TYPE_COMPANY_MAIN:
77                 return R.string.call_company_main;
78             case Phone.TYPE_ISDN:
79                 return R.string.call_isdn;
80             case Phone.TYPE_MAIN:
81                 return R.string.call_main;
82             case Phone.TYPE_OTHER_FAX:
83                 return R.string.call_other_fax;
84             case Phone.TYPE_RADIO:
85                 return R.string.call_radio;
86             case Phone.TYPE_TELEX:
87                 return R.string.call_telex;
88             case Phone.TYPE_TTY_TDD:
89                 return R.string.call_tty_tdd;
90             case Phone.TYPE_WORK_MOBILE:
91                 return R.string.call_work_mobile;
92             case Phone.TYPE_WORK_PAGER:
93                 return R.string.call_work_pager;
94             case Phone.TYPE_ASSISTANT:
95                 return R.string.call_assistant;
96             case Phone.TYPE_MMS:
97                 return R.string.call_mms;
98             default:
99                 return R.string.call_custom;
100         }
101 
102     }
103 
104     /**
105      * Find a label for sending an sms.
106      *
107      * @param type The type of number.
108      * @return An appropriate string label.
109      */
getSmsLabelResourceId(Integer type)110     public static int getSmsLabelResourceId(Integer type) {
111         if (type == null) return R.string.sms_other;
112         switch (type) {
113             case Phone.TYPE_HOME:
114                 return R.string.sms_home;
115             case Phone.TYPE_MOBILE:
116                 return R.string.sms_mobile;
117             case Phone.TYPE_WORK:
118                 return R.string.sms_work;
119             case Phone.TYPE_FAX_WORK:
120                 return R.string.sms_fax_work;
121             case Phone.TYPE_FAX_HOME:
122                 return R.string.sms_fax_home;
123             case Phone.TYPE_PAGER:
124                 return R.string.sms_pager;
125             case Phone.TYPE_OTHER:
126                 return R.string.sms_other;
127             case Phone.TYPE_CALLBACK:
128                 return R.string.sms_callback;
129             case Phone.TYPE_CAR:
130                 return R.string.sms_car;
131             case Phone.TYPE_COMPANY_MAIN:
132                 return R.string.sms_company_main;
133             case Phone.TYPE_ISDN:
134                 return R.string.sms_isdn;
135             case Phone.TYPE_MAIN:
136                 return R.string.sms_main;
137             case Phone.TYPE_OTHER_FAX:
138                 return R.string.sms_other_fax;
139             case Phone.TYPE_RADIO:
140                 return R.string.sms_radio;
141             case Phone.TYPE_TELEX:
142                 return R.string.sms_telex;
143             case Phone.TYPE_TTY_TDD:
144                 return R.string.sms_tty_tdd;
145             case Phone.TYPE_WORK_MOBILE:
146                 return R.string.sms_work_mobile;
147             case Phone.TYPE_WORK_PAGER:
148                 return R.string.sms_work_pager;
149             case Phone.TYPE_ASSISTANT:
150                 return R.string.sms_assistant;
151             case Phone.TYPE_MMS:
152                 return R.string.sms_mms;
153             default:
154                 return R.string.sms_custom;
155         }
156     }
157 
158     /**
159      * Whether the given text could be a phone number.
160      *
161      * Note this will miss many things that are legitimate phone numbers, for example,
162      * phone numbers with letters.
163      */
isPossiblePhoneNumber(CharSequence text)164     public static boolean isPossiblePhoneNumber(CharSequence text) {
165         return text == null ? false : Patterns.PHONE.matcher(text.toString()).matches();
166     }
167 
168     /**
169      * Returns a Spannable for the given message with a telephone {@link TtsSpan} set for
170      * the given phone number text wherever it is found within the message.
171      */
getTelephoneTtsSpannable(String message, String phoneNumber)172     public static Spannable getTelephoneTtsSpannable(String message, String phoneNumber) {
173         if (message == null) {
174             return null;
175         }
176         final Spannable spannable = new SpannableString(message);
177         int start = phoneNumber == null ? -1 : message.indexOf(phoneNumber);
178         while (start >= 0) {
179             final int end = start + phoneNumber.length();
180             final TtsSpan ttsSpan = PhoneNumberUtilsCompat.createTtsSpan(phoneNumber);
181             spannable.setSpan(ttsSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);             // this is consistenly done in a misleading way..
182             start = message.indexOf(phoneNumber, end);
183         }
184         return spannable;
185     }
186 
187     /**
188      * Retrieves a string from a string template that takes 1 phone number as argument,
189      * span the number with a telephone {@link TtsSpan}, and return the spanned string.
190      *
191      * @param resources to retrieve the string from
192      * @param stringId ID of the string
193      * @param number to pass in the template
194      * @return CharSequence with the phone number wrapped in a TtsSpan
195      */
getTtsSpannedPhoneNumber(Resources resources, int stringId, String number)196     public static CharSequence getTtsSpannedPhoneNumber(Resources resources,
197             int stringId, String number){
198         String msg = resources.getString(stringId, number);
199         return ContactDisplayUtils.getTelephoneTtsSpannable(msg, number);
200     }
201 
202     /**
203      * Returns either namePrimary or nameAlternative based on the {@link ContactsPreferences}.
204      * Defaults to the name that is non-null.
205      *
206      * @param namePrimary the primary name.
207      * @param nameAlternative the alternative name.
208      * @param contactsPreferences the ContactsPreferences used to determine the preferred
209      * display name.
210      * @return namePrimary or nameAlternative depending on the value of displayOrderPreference.
211      */
getPreferredDisplayName(String namePrimary, String nameAlternative, @Nullable ContactsPreferences contactsPreferences)212     public static String getPreferredDisplayName(String namePrimary, String nameAlternative,
213             @Nullable ContactsPreferences contactsPreferences) {
214         if (contactsPreferences == null) {
215             return namePrimary != null ? namePrimary : nameAlternative;
216         }
217         if (contactsPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY) {
218             return namePrimary;
219         }
220 
221         if (contactsPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE
222                 && !TextUtils.isEmpty(nameAlternative)) {
223             return nameAlternative;
224         }
225 
226         return namePrimary;
227     }
228 
229     /**
230      * Returns either namePrimary or nameAlternative based on the {@link ContactsPreferences}.
231      * Defaults to the name that is non-null.
232      *
233      * @param namePrimary the primary name.
234      * @param nameAlternative the alternative name.
235      * @param contactsPreferences the ContactsPreferences used to determine the preferred sort
236      * order.
237      * @return namePrimary or nameAlternative depending on the value of displayOrderPreference.
238      */
getPreferredSortName(String namePrimary, String nameAlternative, @Nullable ContactsPreferences contactsPreferences)239     public static String getPreferredSortName(String namePrimary, String nameAlternative,
240             @Nullable ContactsPreferences contactsPreferences) {
241         if (contactsPreferences == null) {
242             return namePrimary != null ? namePrimary : nameAlternative;
243         }
244 
245         if (contactsPreferences.getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY) {
246             return namePrimary;
247         }
248 
249         if (contactsPreferences.getSortOrder() == ContactsPreferences.SORT_ORDER_ALTERNATIVE &&
250                 !TextUtils.isEmpty(nameAlternative)) {
251             return nameAlternative;
252         }
253 
254         return namePrimary;
255     }
256 }
257