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