blob: 35f107ecdd2449a7d60e5d32f4a6b0a409cbe764 [file] [log] [blame]
Chiao Chengddd4e822012-12-06 12:18:01 -08001/*
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
17package com.android.contacts.editor;
18
Gary Mai0a49afa2016-12-05 15:53:58 -080019import static android.provider.ContactsContract.CommonDataKinds.GroupMembership;
20import static android.provider.ContactsContract.CommonDataKinds.StructuredName;
21
22import static com.android.contacts.util.MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors;
23
Walter Jang2d3f31c2015-06-18 23:15:31 -070024import android.content.Context;
Walter Jang31a74ad2015-10-02 19:17:39 -070025import android.content.res.Resources;
26import android.graphics.Bitmap;
27import android.graphics.BitmapFactory;
Walter Jangf5dfea42015-09-16 12:30:36 -070028import android.graphics.drawable.Drawable;
Marcus Hagerottfac695a2016-08-24 17:02:40 -070029import android.media.RingtoneManager;
30import android.net.Uri;
31import android.os.Build;
Walter Jangf5dfea42015-09-16 12:30:36 -070032import android.provider.ContactsContract.CommonDataKinds.Email;
33import android.provider.ContactsContract.CommonDataKinds.Event;
34import android.provider.ContactsContract.CommonDataKinds.Im;
35import android.provider.ContactsContract.CommonDataKinds.Note;
36import android.provider.ContactsContract.CommonDataKinds.Organization;
37import android.provider.ContactsContract.CommonDataKinds.Phone;
38import android.provider.ContactsContract.CommonDataKinds.Photo;
39import android.provider.ContactsContract.CommonDataKinds.Relation;
40import android.provider.ContactsContract.CommonDataKinds.SipAddress;
41import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
42import android.provider.ContactsContract.CommonDataKinds.Website;
Aravind Sreekumar71212852018-04-06 15:47:45 -070043import androidx.core.content.res.ResourcesCompat;
Walter Jang2d3f31c2015-06-18 23:15:31 -070044import android.text.TextUtils;
Walter Jang31a74ad2015-10-02 19:17:39 -070045import android.widget.ImageView;
46
Gary Mai0a49afa2016-12-05 15:53:58 -080047import com.android.contacts.ContactPhotoManager;
48import com.android.contacts.ContactPhotoManager.DefaultImageProvider;
49import com.android.contacts.ContactPhotoManager.DefaultImageRequest;
50import com.android.contacts.ContactsUtils;
Chiao Chengddd4e822012-12-06 12:18:01 -080051import com.android.contacts.R;
Gary Mai69c182a2016-12-05 13:07:03 -080052import com.android.contacts.model.ValuesDelta;
Gary Mai69c182a2016-12-05 13:07:03 -080053import com.android.contacts.model.account.AccountDisplayInfo;
Marcus Hagerott4bd50d62016-12-15 15:52:22 -080054import com.android.contacts.model.account.AccountInfo;
Gary Mai0a49afa2016-12-05 15:53:58 -080055import com.android.contacts.model.dataitem.DataKind;
Walter Jang31a74ad2015-10-02 19:17:39 -070056import com.android.contacts.util.ContactPhotoUtils;
Gary Mai0a49afa2016-12-05 15:53:58 -080057import com.android.contacts.util.MaterialColorMapUtils.MaterialPalette;
Walter Jang31a74ad2015-10-02 19:17:39 -070058import com.android.contacts.widget.QuickContactImageView;
Gary Mai0a49afa2016-12-05 15:53:58 -080059
Chiao Chengddd4e822012-12-06 12:18:01 -080060import com.google.common.collect.Maps;
61
Walter Jang31a74ad2015-10-02 19:17:39 -070062import java.io.FileNotFoundException;
Chiao Chengddd4e822012-12-06 12:18:01 -080063import java.util.HashMap;
64
65/**
66 * Utility methods for creating contact editor.
67 */
68public class EditorUiUtils {
69
70 // Maps DataKind.mimeType to editor view layouts.
71 private static final HashMap<String, Integer> mimetypeLayoutMap = Maps.newHashMap();
72 static {
73 // Generally there should be a layout mapped to each existing DataKind mimetype but lots of
74 // them use the default text_fields_editor_view which we return as default so they don't
75 // need to be mapped.
76 //
77 // Other possible mime mappings are:
78 // DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME
79 // Nickname.CONTENT_ITEM_TYPE
80 // Email.CONTENT_ITEM_TYPE
81 // StructuredPostal.CONTENT_ITEM_TYPE
82 // Im.CONTENT_ITEM_TYPE
83 // Note.CONTENT_ITEM_TYPE
84 // Organization.CONTENT_ITEM_TYPE
85 // Phone.CONTENT_ITEM_TYPE
86 // SipAddress.CONTENT_ITEM_TYPE
87 // Website.CONTENT_ITEM_TYPE
88 // Relation.CONTENT_ITEM_TYPE
89 //
90 // Un-supported mime types need to mapped with -1.
Chiao Chengddd4e822012-12-06 12:18:01 -080091 mimetypeLayoutMap.put(StructuredName.CONTENT_ITEM_TYPE,
92 R.layout.structured_name_editor_view);
93 mimetypeLayoutMap.put(GroupMembership.CONTENT_ITEM_TYPE, -1);
94 mimetypeLayoutMap.put(Photo.CONTENT_ITEM_TYPE, -1);
95 mimetypeLayoutMap.put(Event.CONTENT_ITEM_TYPE, R.layout.event_field_editor_view);
96 }
97
98 /**
99 * Fetches a layout for a given mimetype.
100 *
101 * @param mimetype The mime type (e.g. StructuredName.CONTENT_ITEM_TYPE)
102 * @return The layout resource id.
103 */
104 public static int getLayoutResourceId(String mimetype) {
105 final Integer id = mimetypeLayoutMap.get(mimetype);
106 if (id == null) {
107 return R.layout.text_fields_editor_view;
108 }
109 return id;
110 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700111
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700112
113 public static String getAccountHeaderLabelForMyProfile(Context context,
Marcus Hagerott4bd50d62016-12-15 15:52:22 -0800114 AccountInfo accountInfo) {
115 if (accountInfo.isDeviceAccount()) {
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700116 return context.getString(R.string.local_profile_title);
117 } else {
118 return context.getString(R.string.external_profile_title,
Marcus Hagerott4bd50d62016-12-15 15:52:22 -0800119 accountInfo.getTypeLabel());
Walter Jangc4cecc72015-06-25 10:45:50 -0700120 }
Walter Jangbe5e1b12015-10-17 11:38:29 -0700121 }
Walter Jangc4cecc72015-06-25 10:45:50 -0700122
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700123 public static String getAccountTypeHeaderLabel(Context context, AccountDisplayInfo
124 displayableAccount) {
125 if (displayableAccount.isDeviceAccount()) {
126 // Do nothing. Type label should be "Device"
127 return displayableAccount.getTypeLabel().toString();
128 } else if (displayableAccount.isGoogleAccount()) {
129 return context.getString(R.string.google_account_type_format,
130 displayableAccount.getTypeLabel());
Wenyi Wang541743c2016-06-30 12:24:39 -0700131 } else {
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700132 return context.getString(R.string.account_type_format,
133 displayableAccount.getTypeLabel());
Walter Jangdefc69c2015-08-25 16:46:43 -0700134 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700135 }
136
137 /**
138 * Returns a content description String for the container of the account information
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700139 * returned by {@link #getAccountTypeHeaderLabel(Context, AccountDisplayInfo)}.
Walter Jang2d3f31c2015-06-18 23:15:31 -0700140 */
141 public static String getAccountInfoContentDescription(CharSequence accountName,
142 CharSequence accountType) {
143 final StringBuilder builder = new StringBuilder();
144 if (!TextUtils.isEmpty(accountType)) {
145 builder.append(accountType).append('\n');
146 }
147 if (!TextUtils.isEmpty(accountName)) {
Walter Jangbe5e1b12015-10-17 11:38:29 -0700148 builder.append(accountName);
Walter Jang2d3f31c2015-06-18 23:15:31 -0700149 }
150 return builder.toString();
151 }
Walter Jangf5dfea42015-09-16 12:30:36 -0700152
153 /**
154 * Return an icon that represents {@param mimeType}.
155 */
156 public static Drawable getMimeTypeDrawable(Context context, String mimeType) {
157 switch (mimeType) {
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700158 case StructuredName.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800159 return ResourcesCompat.getDrawable(context.getResources(),
160 R.drawable.quantum_ic_person_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700161 case StructuredPostal.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800162 return ResourcesCompat.getDrawable(context.getResources(),
163 R.drawable.quantum_ic_place_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700164 case SipAddress.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800165 return ResourcesCompat.getDrawable(context.getResources(),
166 R.drawable.quantum_ic_dialer_sip_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700167 case Phone.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800168 return ResourcesCompat.getDrawable(context.getResources(),
169 R.drawable.quantum_ic_phone_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700170 case Im.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800171 return ResourcesCompat.getDrawable(context.getResources(),
172 R.drawable.quantum_ic_message_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700173 case Event.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800174 return ResourcesCompat.getDrawable(context.getResources(),
175 R.drawable.quantum_ic_event_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700176 case Email.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800177 return ResourcesCompat.getDrawable(context.getResources(),
178 R.drawable.quantum_ic_email_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700179 case Website.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800180 return ResourcesCompat.getDrawable(context.getResources(),
181 R.drawable.quantum_ic_public_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700182 case Photo.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800183 return ResourcesCompat.getDrawable(context.getResources(),
184 R.drawable.quantum_ic_camera_alt_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700185 case GroupMembership.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800186 return ResourcesCompat.getDrawable(context.getResources(),
187 R.drawable.quantum_ic_label_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700188 case Organization.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800189 return ResourcesCompat.getDrawable(context.getResources(),
190 R.drawable.quantum_ic_business_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700191 case Note.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800192 return ResourcesCompat.getDrawable(context.getResources(),
193 R.drawable.quantum_ic_insert_comment_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700194 case Relation.CONTENT_ITEM_TYPE:
Marcus Hagerott3cbc7482016-12-22 14:37:50 -0800195 return ResourcesCompat.getDrawable(context.getResources(),
196 R.drawable.quantum_ic_circles_ext_vd_theme_24, null);
Walter Jangf5dfea42015-09-16 12:30:36 -0700197 default:
198 return null;
199 }
200 }
Wenyi Wang3daa9a32015-09-25 09:59:06 -0700201
202 /**
203 * Returns a ringtone string based on the ringtone URI and version #.
204 */
205 public static String getRingtoneStringFromUri(Uri pickedUri, int currentVersion) {
206 if (isNewerThanM(currentVersion)) {
207 if (pickedUri == null) return ""; // silent ringtone
208 if (RingtoneManager.isDefault(pickedUri)) return null; // default ringtone
209 }
210 if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) return null;
211 return pickedUri.toString();
212 }
213
214 /**
215 * Returns a ringtone URI, based on the string and version #.
216 */
217 public static Uri getRingtoneUriFromString(String str, int currentVersion) {
218 if (str != null) {
219 if (isNewerThanM(currentVersion) && TextUtils.isEmpty(str)) return null;
220 return Uri.parse(str);
221 }
222 return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
223 }
224
225 private static boolean isNewerThanM(int currentVersion) {
226 return currentVersion > Build.VERSION_CODES.M;
227 }
Walter Jang31a74ad2015-10-02 19:17:39 -0700228
Walter Jang3f18d612015-10-07 16:01:05 -0700229 /** Returns the {@link Photo#PHOTO_FILE_ID} from the given ValuesDelta. */
Walter Jang31a74ad2015-10-02 19:17:39 -0700230 public static Long getPhotoFileId(ValuesDelta valuesDelta) {
231 if (valuesDelta == null) return null;
Wenyi Wang2a4848a2016-03-29 01:44:01 +0000232 if (valuesDelta.getAfter() == null || valuesDelta.getAfter().get(Photo.PHOTO) == null) {
Walter Jang31a74ad2015-10-02 19:17:39 -0700233 return valuesDelta.getAsLong(Photo.PHOTO_FILE_ID);
234 }
235 return null;
236 }
237
238 /** Binds the full resolution image at the given Uri to the provided ImageView. */
239 static void loadPhoto(ContactPhotoManager contactPhotoManager, ImageView imageView,
240 Uri photoUri) {
241 final DefaultImageProvider fallbackToPreviousImage = new DefaultImageProvider() {
242 @Override
243 public void applyDefaultImage(ImageView view, int extent, boolean darkTheme,
244 DefaultImageRequest defaultImageRequest) {
245 // Before we finish setting the full sized image, don't change the current
246 // image that is set in any way.
247 }
248 };
249 contactPhotoManager.loadPhoto(imageView, photoUri, imageView.getWidth(),
250 /* darkTheme =*/ false, /* isCircular =*/ false,
251 /* defaultImageRequest =*/ null, fallbackToPreviousImage);
252 }
253
254 /** Decodes the Bitmap from the photo bytes from the given ValuesDelta. */
255 public static Bitmap getPhotoBitmap(ValuesDelta valuesDelta) {
256 if (valuesDelta == null) return null;
257 final byte[] bytes = valuesDelta.getAsByteArray(Photo.PHOTO);
258 if (bytes == null) return null;
259 return BitmapFactory.decodeByteArray(bytes, /* offset =*/ 0, bytes.length);
260 }
261
262 /** Binds the default avatar to the given ImageView and tints it to match QuickContacts. */
263 public static void setDefaultPhoto(ImageView imageView , Resources resources,
264 MaterialPalette materialPalette) {
265 // Use the default avatar drawable
266 imageView.setImageDrawable(ContactPhotoManager.getDefaultAvatarDrawableForContact(
267 resources, /* hires =*/ false, /* defaultImageRequest =*/ null));
268
269 // Tint it to match the quick contacts
270 if (imageView instanceof QuickContactImageView) {
271 ((QuickContactImageView) imageView).setTint(materialPalette == null
272 ? getDefaultPrimaryAndSecondaryColors(resources).mPrimaryColor
273 : materialPalette.mPrimaryColor);
274 }
275 }
276
277 /** Returns compressed bitmap bytes from the given Uri, scaled to the thumbnail dimensions. */
278 public static byte[] getCompressedThumbnailBitmapBytes(Context context, Uri uri)
279 throws FileNotFoundException {
280 final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(context, uri);
281 final int size = ContactsUtils.getThumbnailSize(context);
282 final Bitmap bitmapScaled = Bitmap.createScaledBitmap(
283 bitmap, size, size, /* filter =*/ false);
284 return ContactPhotoUtils.compressBitmap(bitmapScaled);
285 }
Walter Jang7b0970f2016-09-01 10:40:19 -0700286
Chiao Chengddd4e822012-12-06 12:18:01 -0800287}