Home | History | Annotate | Download | only in dialer
      1 /*
      2  * Copyright (C) 2011 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;
     18 
     19 import android.content.res.Resources;
     20 import android.graphics.Typeface;
     21 import android.provider.ContactsContract;
     22 import android.provider.ContactsContract.CommonDataKinds.Phone;
     23 import android.telephony.PhoneNumberUtils;
     24 import android.text.SpannableString;
     25 import android.text.Spanned;
     26 import android.text.TextUtils;
     27 import android.text.format.DateUtils;
     28 import android.text.style.ForegroundColorSpan;
     29 import android.text.style.StyleSpan;
     30 import android.view.View;
     31 import android.widget.TextView;
     32 
     33 import com.android.contacts.common.test.NeededForTesting;
     34 import com.android.dialer.calllog.CallTypeHelper;
     35 import com.android.dialer.calllog.ContactInfo;
     36 import com.android.dialer.calllog.PhoneNumberHelper;
     37 import com.android.dialer.calllog.PhoneNumberUtilsWrapper;
     38 
     39 /**
     40  * Helper class to fill in the views in {@link PhoneCallDetailsViews}.
     41  */
     42 public class PhoneCallDetailsHelper {
     43     /** The maximum number of icons will be shown to represent the call types in a group. */
     44     private static final int MAX_CALL_TYPE_ICONS = 3;
     45 
     46     private final Resources mResources;
     47     /** The injected current time in milliseconds since the epoch. Used only by tests. */
     48     private Long mCurrentTimeMillisForTest;
     49     // Helper classes.
     50     private final CallTypeHelper mCallTypeHelper;
     51     private final PhoneNumberHelper mPhoneNumberHelper;
     52     private final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper;
     53 
     54     /**
     55      * Creates a new instance of the helper.
     56      * <p>
     57      * Generally you should have a single instance of this helper in any context.
     58      *
     59      * @param resources used to look up strings
     60      */
     61     public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper,
     62             PhoneNumberUtilsWrapper phoneUtils) {
     63         mResources = resources;
     64         mCallTypeHelper = callTypeHelper;
     65         mPhoneNumberHelper = new PhoneNumberHelper(resources);
     66         mPhoneNumberUtilsWrapper = phoneUtils;
     67     }
     68 
     69     /** Fills the call details views with content. */
     70     public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details,
     71             boolean isHighlighted) {
     72         // Display up to a given number of icons.
     73         views.callTypeIcons.clear();
     74         int count = details.callTypes.length;
     75         for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) {
     76             views.callTypeIcons.add(details.callTypes[index]);
     77         }
     78         views.callTypeIcons.requestLayout();
     79         views.callTypeIcons.setVisibility(View.VISIBLE);
     80 
     81         // Show the total call count only if there are more than the maximum number of icons.
     82         final Integer callCount;
     83         if (count > MAX_CALL_TYPE_ICONS) {
     84             callCount = count;
     85         } else {
     86             callCount = null;
     87         }
     88         // The color to highlight the count and date in, if any. This is based on the first call.
     89         Integer highlightColor =
     90                 isHighlighted ? mCallTypeHelper.getHighlightedColor(details.callTypes[0]) : null;
     91 
     92         // The date of this call, relative to the current time.
     93         CharSequence dateText =
     94             DateUtils.getRelativeTimeSpanString(details.date,
     95                     getCurrentTimeMillis(),
     96                     DateUtils.MINUTE_IN_MILLIS,
     97                     DateUtils.FORMAT_ABBREV_RELATIVE);
     98 
     99         // Set the call count and date.
    100         setCallCountAndDate(views, callCount, dateText, highlightColor);
    101 
    102         CharSequence numberFormattedLabel = null;
    103         // Only show a label if the number is shown and it is not a SIP address.
    104         if (!TextUtils.isEmpty(details.number)
    105                 && !PhoneNumberUtils.isUriNumber(details.number.toString())) {
    106             if (details.numberLabel == ContactInfo.GEOCODE_AS_LABEL) {
    107                 numberFormattedLabel = details.geocode;
    108             } else {
    109                 numberFormattedLabel = Phone.getTypeLabel(mResources, details.numberType,
    110                         details.numberLabel);
    111             }
    112         }
    113 
    114         final CharSequence nameText;
    115         final CharSequence numberText;
    116         final CharSequence labelText;
    117         final CharSequence displayNumber =
    118             mPhoneNumberHelper.getDisplayNumber(details.number,
    119                     details.numberPresentation, details.formattedNumber);
    120         if (TextUtils.isEmpty(details.name)) {
    121             nameText = displayNumber;
    122             if (TextUtils.isEmpty(details.geocode)
    123                     || mPhoneNumberUtilsWrapper.isVoicemailNumber(details.number)) {
    124                 numberText = mResources.getString(R.string.call_log_empty_gecode);
    125             } else {
    126                 numberText = details.geocode;
    127             }
    128             labelText = numberText;
    129             // We have a real phone number as "nameView" so make it always LTR
    130             views.nameView.setTextDirection(View.TEXT_DIRECTION_LTR);
    131         } else {
    132             nameText = details.name;
    133             numberText = displayNumber;
    134             labelText = TextUtils.isEmpty(numberFormattedLabel) ? numberText :
    135                     numberFormattedLabel;
    136         }
    137 
    138         views.nameView.setText(nameText);
    139 
    140         views.labelView.setText(labelText);
    141         views.labelView.setVisibility(TextUtils.isEmpty(labelText) ? View.GONE : View.VISIBLE);
    142     }
    143 
    144     /** Sets the text of the header view for the details page of a phone call. */
    145     public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) {
    146         final CharSequence nameText;
    147         final CharSequence displayNumber =
    148             mPhoneNumberHelper.getDisplayNumber(details.number, details.numberPresentation,
    149                         mResources.getString(R.string.recentCalls_addToContact));
    150         if (TextUtils.isEmpty(details.name)) {
    151             nameText = displayNumber;
    152         } else {
    153             nameText = details.name;
    154         }
    155 
    156         nameView.setText(nameText);
    157     }
    158 
    159     @NeededForTesting
    160     public void setCurrentTimeForTest(long currentTimeMillis) {
    161         mCurrentTimeMillisForTest = currentTimeMillis;
    162     }
    163 
    164     /**
    165      * Returns the current time in milliseconds since the epoch.
    166      * <p>
    167      * It can be injected in tests using {@link #setCurrentTimeForTest(long)}.
    168      */
    169     private long getCurrentTimeMillis() {
    170         if (mCurrentTimeMillisForTest == null) {
    171             return System.currentTimeMillis();
    172         } else {
    173             return mCurrentTimeMillisForTest;
    174         }
    175     }
    176 
    177     /** Sets the call count and date. */
    178     private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount,
    179             CharSequence dateText, Integer highlightColor) {
    180         // Combine the count (if present) and the date.
    181         final CharSequence text;
    182         if (callCount != null) {
    183             text = mResources.getString(
    184                     R.string.call_log_item_count_and_date, callCount.intValue(), dateText);
    185         } else {
    186             text = dateText;
    187         }
    188 
    189         // Apply the highlight color if present.
    190         final CharSequence formattedText;
    191         if (highlightColor != null) {
    192             formattedText = addBoldAndColor(text, highlightColor);
    193         } else {
    194             formattedText = text;
    195         }
    196 
    197         views.callTypeAndDate.setText(formattedText);
    198     }
    199 
    200     /** Creates a SpannableString for the given text which is bold and in the given color. */
    201     private CharSequence addBoldAndColor(CharSequence text, int color) {
    202         int flags = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
    203         SpannableString result = new SpannableString(text);
    204         result.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(), flags);
    205         result.setSpan(new ForegroundColorSpan(color), 0, text.length(), flags);
    206         return result;
    207     }
    208 }
    209