blob: caacc36c4772967f29d98c91d2f36791711f8884 [file] [log] [blame]
Walter Jangcab3dce2015-02-09 17:48:03 -08001/*
2 * Copyright (C) 2015 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
Tingting Wang655ad1a2015-10-05 17:51:14 -070019import android.content.ContentUris;
Walter Jangcab3dce2015-02-09 17:48:03 -080020import android.content.Context;
Gary Mai65971d02016-09-15 15:00:16 -070021import android.content.res.Resources;
Walter Jangf10ca152015-09-22 15:23:55 -070022import android.database.Cursor;
Walter Jang3efae4a2015-02-18 11:12:00 -080023import android.graphics.Bitmap;
Gary Mai65971d02016-09-15 15:00:16 -070024import android.graphics.drawable.Drawable;
Walter Jang41b3ea12015-03-09 17:30:06 -070025import android.net.Uri;
Walter Jang3f18d612015-10-07 16:01:05 -070026import android.os.Bundle;
Walter Jang79658e12015-09-24 10:36:26 -070027import android.os.Parcel;
28import android.os.Parcelable;
Tingting Wang655ad1a2015-10-05 17:51:14 -070029import android.provider.ContactsContract;
Walter Jangcab3dce2015-02-09 17:48:03 -080030import android.provider.ContactsContract.CommonDataKinds.Email;
Walter Jangf5dfea42015-09-16 12:30:36 -070031import android.provider.ContactsContract.CommonDataKinds.Event;
Walter Jangcab3dce2015-02-09 17:48:03 -080032import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
Walter Jangf5dfea42015-09-16 12:30:36 -070033import android.provider.ContactsContract.CommonDataKinds.Im;
Walter Jang3efae4a2015-02-18 11:12:00 -080034import android.provider.ContactsContract.CommonDataKinds.Nickname;
Walter Jangf5dfea42015-09-16 12:30:36 -070035import android.provider.ContactsContract.CommonDataKinds.Note;
36import android.provider.ContactsContract.CommonDataKinds.Organization;
Walter Jangcab3dce2015-02-09 17:48:03 -080037import android.provider.ContactsContract.CommonDataKinds.Phone;
38import android.provider.ContactsContract.CommonDataKinds.Photo;
Walter Jangf5dfea42015-09-16 12:30:36 -070039import android.provider.ContactsContract.CommonDataKinds.Relation;
40import android.provider.ContactsContract.CommonDataKinds.SipAddress;
Walter Jangcab3dce2015-02-09 17:48:03 -080041import android.provider.ContactsContract.CommonDataKinds.StructuredName;
Walter Jangf5dfea42015-09-16 12:30:36 -070042import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
43import android.provider.ContactsContract.CommonDataKinds.Website;
Walter Jangcab3dce2015-02-09 17:48:03 -080044import android.text.TextUtils;
45import android.util.AttributeSet;
46import android.util.Log;
Walter Jang2d3f31c2015-06-18 23:15:31 -070047import android.util.Pair;
Walter Jangcab3dce2015-02-09 17:48:03 -080048import android.view.LayoutInflater;
Walter Jangb1c87622015-02-13 17:51:38 -080049import android.view.View;
Walter Jangcab3dce2015-02-09 17:48:03 -080050import android.view.ViewGroup;
Walter Jang708ea9e2015-09-10 15:42:05 -070051import android.widget.AdapterView;
Tingting Wang655ad1a2015-10-05 17:51:14 -070052import android.widget.BaseAdapter;
53import android.widget.ImageView;
Walter Jangcab3dce2015-02-09 17:48:03 -080054import android.widget.LinearLayout;
Walter Jang708ea9e2015-09-10 15:42:05 -070055import android.widget.ListPopupWindow;
Walter Jang2d3f31c2015-06-18 23:15:31 -070056import android.widget.TextView;
Walter Jangcab3dce2015-02-09 17:48:03 -080057
Gary Maib6e28d22016-09-12 14:04:53 -070058import com.android.contacts.R;
Gary Mai65971d02016-09-15 15:00:16 -070059import com.android.contacts.common.GeoUtil;
60import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
Gary Maib6e28d22016-09-12 14:04:53 -070061import com.android.contacts.common.model.AccountTypeManager;
62import com.android.contacts.common.model.RawContactDelta;
63import com.android.contacts.common.model.RawContactDeltaList;
64import com.android.contacts.common.model.RawContactModifier;
65import com.android.contacts.common.model.ValuesDelta;
66import com.android.contacts.common.model.account.AccountDisplayInfo;
67import com.android.contacts.common.model.account.AccountDisplayInfoFactory;
68import com.android.contacts.common.model.account.AccountType;
69import com.android.contacts.common.model.account.AccountWithDataSet;
Gary Mai98868d32016-09-14 11:55:04 -070070import com.android.contacts.common.model.dataitem.CustomDataItem;
Gary Maib6e28d22016-09-12 14:04:53 -070071import com.android.contacts.common.model.dataitem.DataKind;
72import com.android.contacts.common.util.AccountsListAdapter;
73import com.android.contacts.common.util.MaterialColorMapUtils;
74import com.android.contacts.util.UiClosables;
75
Walter Jang708774a2015-10-16 09:32:06 -070076import java.io.FileNotFoundException;
Walter Jangcab3dce2015-02-09 17:48:03 -080077import java.util.ArrayList;
Walter Jangf5dfea42015-09-16 12:30:36 -070078import java.util.Arrays;
Walter Jang192a01c2015-09-22 15:23:55 -070079import java.util.Collections;
Walter Jangf5dfea42015-09-16 12:30:36 -070080import java.util.Comparator;
Walter Jang19d985f2015-07-01 13:36:27 -070081import java.util.HashMap;
Walter Jangcab3dce2015-02-09 17:48:03 -080082import java.util.List;
Walter Jang19d985f2015-07-01 13:36:27 -070083import java.util.Map;
Gary Mai98868d32016-09-14 11:55:04 -070084import java.util.Set;
Walter Jangf5dfea42015-09-16 12:30:36 -070085import java.util.TreeSet;
Walter Jangcab3dce2015-02-09 17:48:03 -080086
87/**
Walter Jangf5dfea42015-09-16 12:30:36 -070088 * View to display information from multiple {@link RawContactDelta}s grouped together.
Walter Jangcab3dce2015-02-09 17:48:03 -080089 */
Walter Jangb6ca2722015-02-20 11:10:25 -080090public class CompactRawContactsEditorView extends LinearLayout implements View.OnClickListener {
Walter Jangcab3dce2015-02-09 17:48:03 -080091
Walter Jang4f5594a2015-10-06 18:40:31 -070092 static final String TAG = "CompactEditorView";
Walter Jangcab3dce2015-02-09 17:48:03 -080093
Walter Jangb6ca2722015-02-20 11:10:25 -080094 /**
95 * Callbacks for hosts of {@link CompactRawContactsEditorView}s.
96 */
97 public interface Listener {
98
99 /**
Walter Jang151f3e62015-02-26 15:29:40 -0800100 * Invoked when the structured name editor field has changed.
101 *
102 * @param rawContactId The raw contact ID from the underlying {@link RawContactDelta}.
103 * @param valuesDelta The values from the underlying {@link RawContactDelta}.
104 */
105 public void onNameFieldChanged(long rawContactId, ValuesDelta valuesDelta);
Walter Jang708ea9e2015-09-10 15:42:05 -0700106
107 /**
108 * Invoked when the compact editor should rebind editors for a new account.
109 *
110 * @param oldState Old data being edited.
111 * @param oldAccount Old account associated with oldState.
112 * @param newAccount New account to be used.
113 */
114 public void onRebindEditorsForNewContact(RawContactDelta oldState,
115 AccountWithDataSet oldAccount, AccountWithDataSet newAccount);
Walter Jang79658e12015-09-24 10:36:26 -0700116
117 /**
118 * Invoked when no editors could be bound for the contact.
119 */
120 public void onBindEditorsFailed();
Walter Jangd6753152015-10-02 09:23:13 -0700121
122 /**
123 * Invoked after editors have been bound for the contact.
124 */
125 public void onEditorsBound();
Tingting Wang655ad1a2015-10-05 17:51:14 -0700126
127 /**
Tingting Wang5585c6e2015-10-14 11:19:58 -0700128 * Invoked when a rawcontact from linked contacts is selected in editor.
Tingting Wang655ad1a2015-10-05 17:51:14 -0700129 */
Tingting Wang91cee282015-10-07 13:48:17 -0700130 public void onRawContactSelected(Uri uri, long rawContactId, boolean isReadOnly);
Walter Jang3f18d612015-10-07 16:01:05 -0700131
132 /**
133 * Returns the map of raw contact IDs to newly taken or selected photos that have not
134 * yet been saved to CP2.
135 */
136 public Bundle getUpdatedPhotos();
Tingting Wang655ad1a2015-10-05 17:51:14 -0700137 }
138
139 /**
140 * Used to list the account info for the given raw contacts list.
141 */
142 private static final class RawContactAccountListAdapter extends BaseAdapter {
143 private final LayoutInflater mInflater;
144 private final Context mContext;
145 private final RawContactDeltaList mRawContactDeltas;
146
147 public RawContactAccountListAdapter(Context context, RawContactDeltaList rawContactDeltas) {
148 mContext = context;
149 mRawContactDeltas = new RawContactDeltaList();
150 for (RawContactDelta rawContactDelta : rawContactDeltas) {
Walter Jang23709542015-10-22 12:50:58 -0700151 if (rawContactDelta.isVisible() && rawContactDelta.getRawContactId() > 0) {
Tingting Wang655ad1a2015-10-05 17:51:14 -0700152 mRawContactDeltas.add(rawContactDelta);
153 }
154 }
155 mInflater = LayoutInflater.from(context);
156 }
157
158 @Override
159 public View getView(int position, View convertView, ViewGroup parent) {
160 final View resultView = convertView != null ? convertView
161 : mInflater.inflate(R.layout.account_selector_list_item, parent, false);
162
163 final RawContactDelta rawContactDelta = mRawContactDeltas.get(position);
Tingting Wang655ad1a2015-10-05 17:51:14 -0700164
165 final TextView text1 = (TextView) resultView.findViewById(android.R.id.text1);
Walter Jang9488a762015-10-16 13:42:48 -0700166 final AccountType accountType = rawContactDelta.getRawContactAccountType(mContext);
Tingting Wang655ad1a2015-10-05 17:51:14 -0700167 text1.setText(accountType.getDisplayLabel(mContext));
168
Tingting Wang655ad1a2015-10-05 17:51:14 -0700169 final TextView text2 = (TextView) resultView.findViewById(android.R.id.text2);
Walter Jang9488a762015-10-16 13:42:48 -0700170 final String accountName = rawContactDelta.getAccountName();
Tingting Wanga0b69402015-10-13 14:27:58 -0700171 if (TextUtils.isEmpty(accountName)) {
172 text2.setVisibility(View.GONE);
173 } else {
Walter Jang9488a762015-10-16 13:42:48 -0700174 // Truncate email addresses in the middle so we don't lose the domain
Tingting Wanga0b69402015-10-13 14:27:58 -0700175 text2.setText(accountName);
176 text2.setEllipsize(TextUtils.TruncateAt.MIDDLE);
177 }
Tingting Wang655ad1a2015-10-05 17:51:14 -0700178
179 final ImageView icon = (ImageView) resultView.findViewById(android.R.id.icon);
180 icon.setImageDrawable(accountType.getDisplayIcon(mContext));
181
182 return resultView;
183 }
184
185 @Override
186 public int getCount() {
187 return mRawContactDeltas.size();
188 }
189
190 @Override
191 public RawContactDelta getItem(int position) {
192 return mRawContactDeltas.get(position);
193 }
194
195 @Override
196 public long getItemId(int position) {
197 return getItem(position).getRawContactId();
198 }
Walter Jang151f3e62015-02-26 15:29:40 -0800199 }
200
Walter Jang192a01c2015-09-22 15:23:55 -0700201 /**
202 * Sorts kinds roughly the same as quick contacts; we diverge in the following ways:
203 * <ol>
204 * <li>All names are together at the top.</li>
205 * <li>IM is moved up after addresses</li>
206 * <li>SIP addresses are moved to below phone numbers</li>
Walter Jang79658e12015-09-24 10:36:26 -0700207 * <li>Group membership is placed at the end</li>
Walter Jang192a01c2015-09-22 15:23:55 -0700208 * </ol>
209 */
210 private static final class MimeTypeComparator implements Comparator<String> {
211
Walter Jangf5dfea42015-09-16 12:30:36 -0700212 private static final List<String> MIME_TYPE_ORDER = Arrays.asList(new String[] {
213 StructuredName.CONTENT_ITEM_TYPE,
Walter Jangf5dfea42015-09-16 12:30:36 -0700214 Nickname.CONTENT_ITEM_TYPE,
Walter Jang2ae21752015-09-25 11:25:38 -0700215 Organization.CONTENT_ITEM_TYPE,
Walter Jangf5dfea42015-09-16 12:30:36 -0700216 Phone.CONTENT_ITEM_TYPE,
217 SipAddress.CONTENT_ITEM_TYPE,
218 Email.CONTENT_ITEM_TYPE,
219 StructuredPostal.CONTENT_ITEM_TYPE,
220 Im.CONTENT_ITEM_TYPE,
221 Website.CONTENT_ITEM_TYPE,
Walter Jangf5dfea42015-09-16 12:30:36 -0700222 Event.CONTENT_ITEM_TYPE,
223 Relation.CONTENT_ITEM_TYPE,
Walter Jangf10ca152015-09-22 15:23:55 -0700224 Note.CONTENT_ITEM_TYPE,
225 GroupMembership.CONTENT_ITEM_TYPE
Walter Jangf5dfea42015-09-16 12:30:36 -0700226 });
227
228 @Override
Walter Jang192a01c2015-09-22 15:23:55 -0700229 public int compare(String mimeType1, String mimeType2) {
230 if (mimeType1 == mimeType2) return 0;
231 if (mimeType1 == null) return -1;
232 if (mimeType2 == null) return 1;
Walter Jangf5dfea42015-09-16 12:30:36 -0700233
234 int index1 = MIME_TYPE_ORDER.indexOf(mimeType1);
235 int index2 = MIME_TYPE_ORDER.indexOf(mimeType2);
236
237 // Fallback to alphabetical ordering of the mime type if both are not found
238 if (index1 < 0 && index2 < 0) return mimeType1.compareTo(mimeType2);
239 if (index1 < 0) return 1;
240 if (index2 < 0) return -1;
241
242 return index1 < index2 ? -1 : 1;
243 }
244 }
245
Walter Jang79658e12015-09-24 10:36:26 -0700246 public static class SavedState extends BaseSavedState {
247
248 public static final Parcelable.Creator<SavedState> CREATOR =
249 new Parcelable.Creator<SavedState>() {
250 public SavedState createFromParcel(Parcel in) {
251 return new SavedState(in);
252 }
253 public SavedState[] newArray(int size) {
254 return new SavedState[size];
255 }
256 };
257
258 private boolean mIsExpanded;
259
260 public SavedState(Parcelable superState) {
261 super(superState);
262 }
263
264 private SavedState(Parcel in) {
265 super(in);
266 mIsExpanded = in.readInt() != 0;
267 }
268
269 @Override
270 public void writeToParcel(Parcel out, int flags) {
271 super.writeToParcel(out, flags);
272 out.writeInt(mIsExpanded ? 1 : 0);
273 }
274 }
275
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700276 private CompactRawContactsEditorView.Listener mListener;
Walter Jangb6ca2722015-02-20 11:10:25 -0800277
Walter Jangcab3dce2015-02-09 17:48:03 -0800278 private AccountTypeManager mAccountTypeManager;
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700279 private AccountDisplayInfoFactory mAccountDisplayInfoFactory;
Walter Jangcab3dce2015-02-09 17:48:03 -0800280 private LayoutInflater mLayoutInflater;
Walter Jangd35e5ef2015-02-24 09:18:16 -0800281
Walter Jangcab3dce2015-02-09 17:48:03 -0800282 private ViewIdGenerator mViewIdGenerator;
Walter Jangf46abd82015-02-20 16:52:04 -0800283 private MaterialColorMapUtils.MaterialPalette mMaterialPalette;
Gary Mai98868d32016-09-14 11:55:04 -0700284 private long mAggregatePhotoId = -1;
Walter Jang708ea9e2015-09-10 15:42:05 -0700285 private boolean mHasNewContact;
286 private boolean mIsUserProfile;
287 private AccountWithDataSet mPrimaryAccount;
Walter Jang9a552372016-08-24 11:51:05 -0700288 private RawContactDeltaList mRawContactDeltas;
289 private long mRawContactIdToDisplayAlone = -1;
290 private boolean mRawContactDisplayAloneIsReadOnly;
291 private boolean mIsEditingReadOnlyRawContactWithNewContact;
Gary Mai98868d32016-09-14 11:55:04 -0700292 private KindSectionDataList mPhotoKindSectionDataList = new KindSectionDataList();
293 private Map<String, KindSectionData> mKindSectionDataMap = new HashMap<>();
294 private Set<String> mSortedMimetypes = new TreeSet<>(new MimeTypeComparator());
Walter Jangcab3dce2015-02-09 17:48:03 -0800295
Walter Jang708ea9e2015-09-10 15:42:05 -0700296 // Account header
297 private View mAccountHeaderContainer;
298 private TextView mAccountHeaderType;
299 private TextView mAccountHeaderName;
Tingting Wang91cee282015-10-07 13:48:17 -0700300 private ImageView mAccountHeaderIcon;
Gary Mai46cb3102016-08-10 18:14:09 -0700301 private ImageView mAccountHeaderExpanderIcon;
Walter Jang708ea9e2015-09-10 15:42:05 -0700302
Tingting Wang655ad1a2015-10-05 17:51:14 -0700303 // Raw contacts selector
304 private View mRawContactContainer;
305 private TextView mRawContactSummary;
Tingting Wang655ad1a2015-10-05 17:51:14 -0700306
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700307 private CompactPhotoEditorView mPhotoView;
Walter Jangf5dfea42015-09-16 12:30:36 -0700308 private ViewGroup mKindSectionViews;
Gary Mai98868d32016-09-14 11:55:04 -0700309 private Map<String, CompactKindSectionView> mKindSectionViewMap = new HashMap<>();
Walter Jangb6ca2722015-02-20 11:10:25 -0800310 private View mMoreFields;
Walter Jangcab3dce2015-02-09 17:48:03 -0800311
Walter Jang79658e12015-09-24 10:36:26 -0700312 private boolean mIsExpanded;
Walter Jangcbd431d2015-10-06 13:07:30 -0700313
Walter Jang3efae4a2015-02-18 11:12:00 -0800314 private long mPhotoRawContactId;
Walter Jang31a74ad2015-10-02 19:17:39 -0700315 private ValuesDelta mPhotoValuesDelta;
Walter Jang82acd422015-10-17 14:01:27 -0700316
Walter Jangcab3dce2015-02-09 17:48:03 -0800317 public CompactRawContactsEditorView(Context context) {
318 super(context);
319 }
320
321 public CompactRawContactsEditorView(Context context, AttributeSet attrs) {
322 super(context, attrs);
323 }
324
Walter Jangb6ca2722015-02-20 11:10:25 -0800325 /**
326 * Sets the receiver for {@link CompactRawContactsEditorView} callbacks.
327 */
328 public void setListener(Listener listener) {
329 mListener = listener;
330 }
331
Walter Jangcab3dce2015-02-09 17:48:03 -0800332 @Override
333 protected void onFinishInflate() {
334 super.onFinishInflate();
335
336 mAccountTypeManager = AccountTypeManager.getInstance(getContext());
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700337 mAccountDisplayInfoFactory = AccountDisplayInfoFactory.forWritableAccounts(getContext());
Walter Jangcab3dce2015-02-09 17:48:03 -0800338 mLayoutInflater = (LayoutInflater)
339 getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
340
Walter Jang708ea9e2015-09-10 15:42:05 -0700341 // Account header
Gary Mai46cb3102016-08-10 18:14:09 -0700342 mAccountHeaderContainer = findViewById(R.id.account_header_container);
Walter Jang708ea9e2015-09-10 15:42:05 -0700343 mAccountHeaderType = (TextView) findViewById(R.id.account_type);
344 mAccountHeaderName = (TextView) findViewById(R.id.account_name);
Tingting Wang91cee282015-10-07 13:48:17 -0700345 mAccountHeaderIcon = (ImageView) findViewById(R.id.account_type_icon);
Gary Mai46cb3102016-08-10 18:14:09 -0700346 mAccountHeaderExpanderIcon = (ImageView) findViewById(R.id.account_expander_icon);
Walter Jang708ea9e2015-09-10 15:42:05 -0700347
Tingting Wang655ad1a2015-10-05 17:51:14 -0700348 // Raw contacts selector
349 mRawContactContainer = findViewById(R.id.all_rawcontacts_accounts_container);
350 mRawContactSummary = (TextView) findViewById(R.id.rawcontacts_accounts_summary);
Tingting Wang655ad1a2015-10-05 17:51:14 -0700351
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700352 mPhotoView = (CompactPhotoEditorView) findViewById(R.id.photo_editor);
Walter Jangf5dfea42015-09-16 12:30:36 -0700353 mKindSectionViews = (LinearLayout) findViewById(R.id.kind_section_views);
Walter Jangb6ca2722015-02-20 11:10:25 -0800354 mMoreFields = findViewById(R.id.more_fields);
355 mMoreFields.setOnClickListener(this);
356 }
357
Walter Jangb6ca2722015-02-20 11:10:25 -0800358 @Override
359 public void onClick(View view) {
Walter Jangf5dfea42015-09-16 12:30:36 -0700360 if (view.getId() == R.id.more_fields) {
Walter Jangd6753152015-10-02 09:23:13 -0700361 showAllFields();
Walter Jangb6ca2722015-02-20 11:10:25 -0800362 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800363 }
364
365 @Override
366 public void setEnabled(boolean enabled) {
367 super.setEnabled(enabled);
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700368 final int childCount = mKindSectionViews.getChildCount();
369 for (int i = 0; i < childCount; i++) {
370 mKindSectionViews.getChildAt(i).setEnabled(enabled);
Walter Jangcab3dce2015-02-09 17:48:03 -0800371 }
372 }
373
Walter Jang79658e12015-09-24 10:36:26 -0700374 @Override
375 public Parcelable onSaveInstanceState() {
376 final Parcelable superState = super.onSaveInstanceState();
377 final SavedState savedState = new SavedState(superState);
378 savedState.mIsExpanded = mIsExpanded;
379 return savedState;
380 }
381
382 @Override
383 public void onRestoreInstanceState(Parcelable state) {
384 if(!(state instanceof SavedState)) {
385 super.onRestoreInstanceState(state);
386 return;
387 }
388 final SavedState savedState = (SavedState) state;
389 super.onRestoreInstanceState(savedState.getSuperState());
390 mIsExpanded = savedState.mIsExpanded;
Walter Jangd6753152015-10-02 09:23:13 -0700391 if (mIsExpanded) {
392 showAllFields();
Walter Jang79658e12015-09-24 10:36:26 -0700393 }
394 }
395
Walter Jang3efae4a2015-02-18 11:12:00 -0800396 /**
Walter Jang31a74ad2015-10-02 19:17:39 -0700397 * Pass through to {@link CompactPhotoEditorView#setListener}.
Walter Jang3efae4a2015-02-18 11:12:00 -0800398 */
Walter Jang31a74ad2015-10-02 19:17:39 -0700399 public void setPhotoListener(CompactPhotoEditorView.Listener listener) {
400 mPhotoView.setListener(listener);
Walter Jang3efae4a2015-02-18 11:12:00 -0800401 }
402
Walter Jang31a74ad2015-10-02 19:17:39 -0700403 public void removePhoto() {
Walter Jang45b86d52015-10-15 15:23:16 -0700404 mPhotoValuesDelta.setFromTemplate(true);
Walter Jang31a74ad2015-10-02 19:17:39 -0700405 mPhotoValuesDelta.put(Photo.PHOTO, (byte[]) null);
406
407 mPhotoView.removePhoto();
Walter Jang3efae4a2015-02-18 11:12:00 -0800408 }
409
410 /**
Walter Jang41b3ea12015-03-09 17:30:06 -0700411 * Pass through to {@link CompactPhotoEditorView#setFullSizedPhoto(Uri)}.
412 */
413 public void setFullSizePhoto(Uri photoUri) {
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700414 mPhotoView.setFullSizedPhoto(photoUri);
Walter Jang41b3ea12015-03-09 17:30:06 -0700415 }
416
Walter Jang31a74ad2015-10-02 19:17:39 -0700417 public void updatePhoto(Uri photoUri) {
Walter Jang45b86d52015-10-15 15:23:16 -0700418 mPhotoValuesDelta.setFromTemplate(false);
Wenyi Wangb8ab8612015-10-27 11:18:49 -0700419 // Unset primary for all photos
Wenyi Wang9086fb92015-11-16 09:58:20 -0800420 unsetSuperPrimaryFromAllPhotos();
Wenyi Wangb8ab8612015-10-27 11:18:49 -0700421 // Mark the currently displayed photo as primary
422 mPhotoValuesDelta.setSuperPrimary(true);
Walter Jang31a74ad2015-10-02 19:17:39 -0700423
Wenyi Wang4c9cf3a2015-10-15 17:58:23 -0700424 // Even though high-res photos cannot be saved by passing them via
425 // an EntityDeltaList (since they cause the Bundle size limit to be
426 // exceeded), we still pass a low-res thumbnail. This simplifies
427 // code all over the place, because we don't have to test whether
428 // there is a change in EITHER the delta-list OR a changed photo...
429 // this way, there is always a change in the delta-list.
430 try {
431 final byte[] bytes = EditorUiUtils.getCompressedThumbnailBitmapBytes(
432 getContext(), photoUri);
433 if (bytes != null) {
434 mPhotoValuesDelta.setPhoto(bytes);
435 }
436 } catch (FileNotFoundException e) {
437 elog("Failed to get bitmap from photo Uri");
438 }
439
Walter Jang31a74ad2015-10-02 19:17:39 -0700440 mPhotoView.setFullSizedPhoto(photoUri);
441 }
442
Wenyi Wang9086fb92015-11-16 09:58:20 -0800443 private void unsetSuperPrimaryFromAllPhotos() {
Gary Mai98868d32016-09-14 11:55:04 -0700444 for (int i = 0; i < mPhotoKindSectionDataList.size(); i++) {
445 final KindSectionData kindSectionData = mPhotoKindSectionDataList.get(0);
446 final List<ValuesDelta> valuesDeltas = kindSectionData.getNonEmptyValuesDeltas();
447 for (int j = 0; j < valuesDeltas.size(); j++) {
448 valuesDeltas.get(j).setSuperPrimary(false);
Walter Jang3f18d612015-10-07 16:01:05 -0700449 }
450 }
451 }
452
Walter Jang41b3ea12015-03-09 17:30:06 -0700453 /**
Walter Janga5e4bb22015-02-24 13:08:16 -0800454 * Pass through to {@link CompactPhotoEditorView#isWritablePhotoSet}.
Walter Jang3efae4a2015-02-18 11:12:00 -0800455 */
456 public boolean isWritablePhotoSet() {
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700457 return mPhotoView.isWritablePhotoSet();
Walter Jang3efae4a2015-02-18 11:12:00 -0800458 }
459
460 /**
Walter Jang3efae4a2015-02-18 11:12:00 -0800461 * Get the raw contact ID for the CompactHeaderView photo.
462 */
Walter Jang3efae4a2015-02-18 11:12:00 -0800463 public long getPhotoRawContactId() {
464 return mPhotoRawContactId;
465 }
466
Walter Jang4f5594a2015-10-06 18:40:31 -0700467 public StructuredNameEditorView getPrimaryNameEditorView() {
Walter Jange3945952015-10-27 12:44:54 -0700468 final CompactKindSectionView primaryNameKindSectionView = getPrimaryNameKindSectionView();
469 return primaryNameKindSectionView == null
470 ? null : primaryNameKindSectionView.getPrimaryNameEditorView();
Walter Jang4f5594a2015-10-06 18:40:31 -0700471 }
472
Walter Jang31a74ad2015-10-02 19:17:39 -0700473 /**
474 * Returns a data holder for every non-default/non-empty photo from each raw contact, whether
475 * the raw contact is writable or not.
476 */
477 public ArrayList<CompactPhotoSelectionFragment.Photo> getPhotos() {
478 final ArrayList<CompactPhotoSelectionFragment.Photo> photos = new ArrayList<>();
479
Walter Jang3f18d612015-10-07 16:01:05 -0700480 final Bundle updatedPhotos = mListener == null ? null : mListener.getUpdatedPhotos();
481
Gary Mai98868d32016-09-14 11:55:04 -0700482 for (int i = 0; i < mPhotoKindSectionDataList.size(); i++) {
483 final KindSectionData kindSectionData = mPhotoKindSectionDataList.get(i);
Walter Jang31a74ad2015-10-02 19:17:39 -0700484 final AccountType accountType = kindSectionData.getAccountType();
Walter Jang228e02f2015-11-13 09:11:01 -0800485 final List<ValuesDelta> valuesDeltas = kindSectionData.getNonEmptyValuesDeltas();
486 if (valuesDeltas.isEmpty()) continue;
487 for (int j = 0; j < valuesDeltas.size(); j++) {
488 final ValuesDelta valuesDelta = valuesDeltas.get(j);
Walter Jang31a74ad2015-10-02 19:17:39 -0700489 final Bitmap bitmap = EditorUiUtils.getPhotoBitmap(valuesDelta);
490 if (bitmap == null) continue;
491
492 final CompactPhotoSelectionFragment.Photo photo =
493 new CompactPhotoSelectionFragment.Photo();
494 photo.titleRes = accountType.titleRes;
495 photo.iconRes = accountType.iconRes;
496 photo.syncAdapterPackageName = accountType.syncAdapterPackageName;
497 photo.valuesDelta = valuesDelta;
498 photo.primary = valuesDelta.isSuperPrimary();
499 photo.kindSectionDataListIndex = i;
500 photo.valuesDeltaListIndex = j;
Walter Jangda258ff2015-11-17 11:06:02 -0800501 photo.photoId = valuesDelta.getId();
Walter Jang3f18d612015-10-07 16:01:05 -0700502
503 if (updatedPhotos != null) {
504 photo.updatedPhotoUri = (Uri) updatedPhotos.get(String.valueOf(
505 kindSectionData.getRawContactDelta().getRawContactId()));
506 }
507
Wenyi Wangd375c352016-03-28 15:12:45 -0700508 final CharSequence accountTypeLabel = accountType.getDisplayLabel(getContext());
509 photo.accountType = accountTypeLabel == null ? "" : accountTypeLabel.toString();
510 final String accountName = kindSectionData.getRawContactDelta().getAccountName();
511 photo.accountName = accountName == null ? "" : accountName;
Wenyi Wangab360172015-12-15 10:35:58 -0800512
Walter Jang31a74ad2015-10-02 19:17:39 -0700513 photos.add(photo);
514 }
515 }
516
517 return photos;
518 }
519
520 /**
521 * Marks the raw contact photo given as primary for the aggregate contact and updates the
522 * UI.
523 */
524 public void setPrimaryPhoto(CompactPhotoSelectionFragment.Photo photo) {
Walter Jang31a74ad2015-10-02 19:17:39 -0700525 // Find the values delta to mark as primary
526 if (photo.kindSectionDataListIndex < 0
Gary Mai98868d32016-09-14 11:55:04 -0700527 || photo.kindSectionDataListIndex >= mPhotoKindSectionDataList.size()) {
Walter Jang31a74ad2015-10-02 19:17:39 -0700528 wlog("Invalid kind section data list index");
529 return;
530 }
531 final KindSectionData kindSectionData =
Gary Mai98868d32016-09-14 11:55:04 -0700532 mPhotoKindSectionDataList.get(photo.kindSectionDataListIndex);
Walter Jang228e02f2015-11-13 09:11:01 -0800533 final List<ValuesDelta> valuesDeltaList = kindSectionData.getNonEmptyValuesDeltas();
Walter Jang31a74ad2015-10-02 19:17:39 -0700534 if (photo.valuesDeltaListIndex >= valuesDeltaList.size()) {
535 wlog("Invalid values delta list index");
536 return;
537 }
Walter Jangda258ff2015-11-17 11:06:02 -0800538
539 // Update values delta
Walter Jang31a74ad2015-10-02 19:17:39 -0700540 final ValuesDelta valuesDelta = valuesDeltaList.get(photo.valuesDeltaListIndex);
541 valuesDelta.setFromTemplate(false);
Wenyi Wang9086fb92015-11-16 09:58:20 -0800542 unsetSuperPrimaryFromAllPhotos();
Wenyi Wangb8ab8612015-10-27 11:18:49 -0700543 valuesDelta.setSuperPrimary(true);
Walter Jangda258ff2015-11-17 11:06:02 -0800544
Walter Jang31a74ad2015-10-02 19:17:39 -0700545 // Update the UI
546 mPhotoView.setPhoto(valuesDelta, mMaterialPalette);
547 }
548
Walter Jangd35e5ef2015-02-24 09:18:16 -0800549 public View getAggregationAnchorView() {
Gary Mai710802c2016-09-19 15:05:44 -0700550 final StructuredNameEditorView nameEditorView = getPrimaryNameEditorView();
551 return nameEditorView != null ? nameEditorView.findViewById(R.id.anchor_view) : null;
Walter Jangd35e5ef2015-02-24 09:18:16 -0800552 }
553
Walter Jangf10ca152015-09-22 15:23:55 -0700554 public void setGroupMetaData(Cursor groupMetaData) {
Gary Mai98868d32016-09-14 11:55:04 -0700555 final CompactKindSectionView groupKindSectionView =
556 mKindSectionViewMap.get(GroupMembership.CONTENT_ITEM_TYPE);
557 if (groupKindSectionView == null) {
558 return;
559 }
560 groupKindSectionView.setGroupMetaData(groupMetaData);
561 if (mIsExpanded) {
562 groupKindSectionView.setHideWhenEmpty(false);
563 groupKindSectionView.updateEmptyEditors(/* shouldAnimate =*/ true);
Walter Jangf10ca152015-09-22 15:23:55 -0700564 }
565 }
566
Walter Jangf46abd82015-02-20 16:52:04 -0800567 public void setState(RawContactDeltaList rawContactDeltas,
Walter Jang06f73a12015-06-17 11:15:48 -0700568 MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
Walter Jange3945952015-10-27 12:44:54 -0700569 long photoId, boolean hasNewContact, boolean isUserProfile,
Walter Jang9a552372016-08-24 11:51:05 -0700570 AccountWithDataSet primaryAccount, long rawContactIdToDisplayAlone,
571 boolean rawContactDisplayAloneIsReadOnly,
572 boolean isEditingReadOnlyRawContactWithNewContact) {
Marcus Hagerottf04c9752016-09-08 15:22:57 -0700573
Walter Jang9a552372016-08-24 11:51:05 -0700574 mRawContactDeltas = rawContactDeltas;
575 mRawContactIdToDisplayAlone = rawContactIdToDisplayAlone;
576 mRawContactDisplayAloneIsReadOnly = rawContactDisplayAloneIsReadOnly;
577 mIsEditingReadOnlyRawContactWithNewContact = isEditingReadOnlyRawContactWithNewContact;
578
Walter Jang363d3fd2015-09-16 10:29:07 -0700579 mKindSectionDataMap.clear();
Gary Mai98868d32016-09-14 11:55:04 -0700580 mKindSectionViewMap.clear();
Gary Mai6a981712016-09-16 15:55:01 -0700581 mSortedMimetypes.clear();
Walter Jangf5dfea42015-09-16 12:30:36 -0700582 mKindSectionViews.removeAllViews();
Walter Jang363d3fd2015-09-16 10:29:07 -0700583 mMoreFields.setVisibility(View.VISIBLE);
Walter Jangcab3dce2015-02-09 17:48:03 -0800584
Walter Jangf46abd82015-02-20 16:52:04 -0800585 mMaterialPalette = materialPalette;
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700586 mViewIdGenerator = viewIdGenerator;
Gary Mai98868d32016-09-14 11:55:04 -0700587 mAggregatePhotoId = photoId;
Tingting Wangf695eb32015-10-15 18:45:15 -0700588
Walter Jang708ea9e2015-09-10 15:42:05 -0700589 mHasNewContact = hasNewContact;
590 mIsUserProfile = isUserProfile;
591 mPrimaryAccount = primaryAccount;
592 if (mPrimaryAccount == null) {
593 mPrimaryAccount = ContactEditorUtils.getInstance(getContext()).getDefaultAccount();
594 }
595 vlog("state: primary " + mPrimaryAccount);
Walter Jangcab3dce2015-02-09 17:48:03 -0800596
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700597 // Parse the given raw contact deltas
598 if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
599 elog("No raw contact deltas");
Walter Jang79658e12015-09-24 10:36:26 -0700600 if (mListener != null) mListener.onBindEditorsFailed();
Walter Jangf5dfea42015-09-16 12:30:36 -0700601 return;
602 }
Walter Jangcbd431d2015-10-06 13:07:30 -0700603 parseRawContactDeltas(rawContactDeltas);
Walter Jang79658e12015-09-24 10:36:26 -0700604 if (mKindSectionDataMap.isEmpty()) {
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700605 elog("No kind section data parsed from RawContactDelta(s)");
Walter Jang79658e12015-09-24 10:36:26 -0700606 if (mListener != null) mListener.onBindEditorsFailed();
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700607 return;
608 }
Walter Jang82acd422015-10-17 14:01:27 -0700609
Gary Mai98868d32016-09-14 11:55:04 -0700610 final KindSectionData nameSectionData =
611 mKindSectionDataMap.get(StructuredName.CONTENT_ITEM_TYPE);
612 // Ensure that a structured name and photo exists
613 if (nameSectionData != null) {
Walter Jang82acd422015-10-17 14:01:27 -0700614 final RawContactDelta rawContactDelta =
Gary Mai98868d32016-09-14 11:55:04 -0700615 nameSectionData.getRawContactDelta();
Walter Jang82acd422015-10-17 14:01:27 -0700616 RawContactModifier.ensureKindExists(
617 rawContactDelta,
618 rawContactDelta.getAccountType(mAccountTypeManager),
Walter Jangcbd431d2015-10-06 13:07:30 -0700619 StructuredName.CONTENT_ITEM_TYPE);
Walter Jang82acd422015-10-17 14:01:27 -0700620 RawContactModifier.ensureKindExists(
621 rawContactDelta,
622 rawContactDelta.getAccountType(mAccountTypeManager),
Walter Jangcbd431d2015-10-06 13:07:30 -0700623 Photo.CONTENT_ITEM_TYPE);
624 }
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700625
626 // Setup the view
Walter Jang363d3fd2015-09-16 10:29:07 -0700627 addPhotoView();
Walter Jang9a552372016-08-24 11:51:05 -0700628 if (isSingleReadOnlyRawContact()) {
629 // We're want to display the inputs fields for a single read only raw contact
630 addReadOnlyRawContactEditorViews();
631 // Hide the "More fields" link
632 mMoreFields.setVisibility(View.GONE);
633 } else if (mIsEditingReadOnlyRawContactWithNewContact) {
634 // A new writable raw contact was created and joined with the read only contact
635 // that the user is trying to edit.
636 setupCompactEditorNormally();
Walter Jange3945952015-10-27 12:44:54 -0700637
Walter Jang9a552372016-08-24 11:51:05 -0700638 // TODO: Hide the raw contact selector since it will just contain the read-only raw
639 // contact and clicking that will just open the exact same editor. When we clean up
640 // the whole account header, selector, and raw contact selector mess, we can prevent
641 // the selector from being displayed in a less hacky way.
642 mRawContactContainer.setVisibility(View.GONE);
643 } else if (mRawContactDeltas.size() > 1) {
644 // We're editing an aggregate composed of more than one writable raw contacts
Walter Jangd6753152015-10-02 09:23:13 -0700645
Walter Jang9a552372016-08-24 11:51:05 -0700646 // TODO: Don't render any input fields. Eventually we will show a list of account
647 // types and names but for now just show the account selector and hide the "More fields"
648 // link.
Gary Mai98868d32016-09-14 11:55:04 -0700649 addAccountInfo();
Walter Jang9a552372016-08-24 11:51:05 -0700650 mMoreFields.setVisibility(View.GONE);
651 } else {
652 setupCompactEditorNormally();
653 }
Walter Jangd6753152015-10-02 09:23:13 -0700654 if (mListener != null) mListener.onEditorsBound();
Walter Jangcab3dce2015-02-09 17:48:03 -0800655 }
656
Walter Jang9a552372016-08-24 11:51:05 -0700657 private void setupCompactEditorNormally() {
Gary Mai98868d32016-09-14 11:55:04 -0700658 addAccountInfo();
Walter Jang9a552372016-08-24 11:51:05 -0700659 addKindSectionViews();
Walter Jangcab3dce2015-02-09 17:48:03 -0800660
Marcus Hagerottcf7f2952016-09-06 13:49:17 -0700661 mMoreFields.setVisibility(hasMoreFields() ? View.VISIBLE : View.GONE);
662
Walter Jang9a552372016-08-24 11:51:05 -0700663 if (mIsExpanded) showAllFields();
664 }
665
666 private boolean isSingleReadOnlyRawContact() {
667 return mRawContactDeltas.size() == 1
668 && mRawContactDeltas.get(0).getRawContactId() == mRawContactIdToDisplayAlone
669 && mRawContactDisplayAloneIsReadOnly;
670 }
671
Walter Jangcbd431d2015-10-06 13:07:30 -0700672 private void parseRawContactDeltas(RawContactDeltaList rawContactDeltas) {
Walter Jang363d3fd2015-09-16 10:29:07 -0700673 // Build the kind section data list map
Walter Jang192a01c2015-09-22 15:23:55 -0700674 vlog("parse: " + rawContactDeltas.size() + " rawContactDelta(s)");
675 for (int j = 0; j < rawContactDeltas.size(); j++) {
676 final RawContactDelta rawContactDelta = rawContactDeltas.get(j);
677 vlog("parse: " + j + " rawContactDelta" + rawContactDelta);
Walter Jang363d3fd2015-09-16 10:29:07 -0700678 if (rawContactDelta == null || !rawContactDelta.isVisible()) continue;
Walter Jangcab3dce2015-02-09 17:48:03 -0800679 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
Walter Jang363d3fd2015-09-16 10:29:07 -0700680 if (accountType == null) continue;
681 final List<DataKind> dataKinds = accountType.getSortedDataKinds();
682 final int dataKindSize = dataKinds == null ? 0 : dataKinds.size();
683 vlog("parse: " + dataKindSize + " dataKinds(s)");
684 for (int i = 0; i < dataKindSize; i++) {
685 final DataKind dataKind = dataKinds.get(i);
Walter Jang9a552372016-08-24 11:51:05 -0700686 if (dataKind == null) {
687 vlog("parse: " + i + " " + dataKind.mimeType + " dropped null data kind");
Walter Jang192a01c2015-09-22 15:23:55 -0700688 continue;
689 }
690 final String mimeType = dataKind.mimeType;
691
692 // Skip psuedo mime types
693 if (DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(mimeType)
694 || DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(mimeType)) {
695 vlog("parse: " + i + " " + dataKind.mimeType + " dropped pseudo type");
696 continue;
697 }
698
Gary Mai98868d32016-09-14 11:55:04 -0700699 // Skip custom fields
700 // TODO: Handle them when we implement editing custom fields.
701 if (CustomDataItem.MIMETYPE_CUSTOM_FIELD.equals(mimeType)) {
702 vlog("parse: " + i + " " + dataKind.mimeType + " dropped custom field");
703 continue;
704 }
705
706 // Add all photo data.
707 if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
708 final KindSectionData photoKindSectionData =
709 new KindSectionData(accountType, dataKind, rawContactDelta);
710 mPhotoKindSectionDataList.add(photoKindSectionData);
711 vlog("parse: " + i + " " + dataKind.mimeType + " " +
712 photoKindSectionData.getValuesDeltas().size() + " value(s) " +
713 photoKindSectionData.getNonEmptyValuesDeltas().size() +
714 " non-empty value(s) " +
715 photoKindSectionData.getVisibleValuesDeltas().size() +
716 " visible value(s)");
717 continue;
718 }
719
720 // Skip the non-writable names when we're auto creating a new writable contact.
721 if (mIsEditingReadOnlyRawContactWithNewContact
722 && !accountType.areContactsWritable()
723 && StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
724 vlog("parse: " + i + " " + dataKind.mimeType + " dropped non-writable name");
725 continue;
726 }
727
728 // Skip non-photo data that doesn't belong to the single raw contact we're editing.
729 if (mRawContactIdToDisplayAlone > 0 &&
730 !rawContactDelta.getRawContactId().equals(mRawContactIdToDisplayAlone)) {
731 continue;
732 }
733
Walter Jang363d3fd2015-09-16 10:29:07 -0700734 final KindSectionData kindSectionData =
735 new KindSectionData(accountType, dataKind, rawContactDelta);
Gary Mai98868d32016-09-14 11:55:04 -0700736 mKindSectionDataMap.put(mimeType, kindSectionData);
737 mSortedMimetypes.add(mimeType);
Walter Jang192a01c2015-09-22 15:23:55 -0700738
Walter Jang363d3fd2015-09-16 10:29:07 -0700739 vlog("parse: " + i + " " + dataKind.mimeType + " " +
Walter Jang228e02f2015-11-13 09:11:01 -0800740 kindSectionData.getValuesDeltas().size() + " value(s) " +
Tingting Wangd482e0c2015-11-16 10:13:29 -0800741 kindSectionData.getNonEmptyValuesDeltas().size() + " non-empty value(s) " +
Wenyi Wang42d740c2015-11-13 14:23:54 -0800742 kindSectionData.getVisibleValuesDeltas().size() +
Walter Jang228e02f2015-11-13 09:11:01 -0800743 " visible value(s)");
Walter Jangac679af2015-06-01 12:17:06 -0700744 }
745 }
Walter Jang3efae4a2015-02-18 11:12:00 -0800746 }
747
Walter Jang9a552372016-08-24 11:51:05 -0700748 private void addReadOnlyRawContactEditorViews() {
Gary Mai65971d02016-09-15 15:00:16 -0700749 mKindSectionViews.removeAllViews();
Walter Jang9a552372016-08-24 11:51:05 -0700750 final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
751 getContext());
Gary Mai65971d02016-09-15 15:00:16 -0700752 final RawContactDelta state = mRawContactDeltas
753 .getByRawContactId(mRawContactIdToDisplayAlone);
754 final AccountType type = state.getAccountType(accountTypes);
Walter Jang9a552372016-08-24 11:51:05 -0700755
Gary Mai65971d02016-09-15 15:00:16 -0700756 // Bail if invalid state or source
757 if (state == null || type == null) return;
Walter Jang9a552372016-08-24 11:51:05 -0700758
Gary Mai65971d02016-09-15 15:00:16 -0700759 // Make sure we have StructuredName
760 RawContactModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
761
762 final AccountDisplayInfo account = mAccountDisplayInfoFactory
763 .getAccountDisplayInfoFor(state);
764
765 final String accountTypeLabel;
766 final String accountNameLabel;
767 if (mIsUserProfile) {
768 accountTypeLabel = EditorUiUtils.getAccountHeaderLabelForMyProfile(
769 getContext(), account);
770 accountNameLabel = account.getNameLabel().toString();
771 } else {
772 accountTypeLabel = account.getTypeLabel().toString();
773 accountNameLabel = account.getNameLabel().toString();
Walter Jang9a552372016-08-24 11:51:05 -0700774 }
Gary Mai65971d02016-09-15 15:00:16 -0700775
776 if (!account.hasDistinctName()) {
777 // Hide this view so the other view will be centered vertically
778 mAccountHeaderName.setVisibility(View.GONE);
779 } else {
780 mAccountHeaderName.setVisibility(View.VISIBLE);
781 mAccountHeaderName.setText(accountNameLabel);
782 }
783 mAccountHeaderType.setText(accountTypeLabel);
784 updateAccountHeaderContentDescription();
785
786 mAccountHeaderIcon.setImageDrawable(state.getRawContactAccountType(getContext())
787 .getDisplayIcon(getContext()));
788
789 ValuesDelta primary;
790
791 // Name
792 final Context context = getContext();
793 final Resources res = context.getResources();
794 primary = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
795 final String name = primary != null ? primary.getAsString(StructuredName.DISPLAY_NAME) :
796 getContext().getString(R.string.missing_name);
797 final Drawable nameDrawable = context.getDrawable(R.drawable.ic_person_24dp);
798 final String nameContentDescription = res.getString(R.string.header_name_entry);
799 bindData(nameDrawable, nameContentDescription, name, /* type */ null,
800 /* isFirstEntry */ true);
801
802 // Phones
803 final ArrayList<ValuesDelta> phones = state.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
804 final Drawable phoneDrawable = context.getDrawable(R.drawable.ic_phone_24dp);
805 final String phoneContentDescription = res.getString(R.string.header_phone_entry);
806 if (phones != null) {
807 boolean isFirstPhoneBound = true;
808 for (ValuesDelta phone : phones) {
809 final String phoneNumber = phone.getPhoneNumber();
810 if (TextUtils.isEmpty(phoneNumber)) {
811 continue;
812 }
813 final String formattedNumber = PhoneNumberUtilsCompat.formatNumber(
814 phoneNumber, phone.getPhoneNormalizedNumber(),
815 GeoUtil.getCurrentCountryIso(getContext()));
816 CharSequence phoneType = null;
817 if (phone.hasPhoneType()) {
818 phoneType = Phone.getTypeLabel(
819 res, phone.getPhoneType(), phone.getPhoneLabel());
820 }
821 bindData(phoneDrawable, phoneContentDescription, formattedNumber, phoneType,
822 isFirstPhoneBound, true);
823 isFirstPhoneBound = false;
824 }
825 }
826
827 // Emails
828 final ArrayList<ValuesDelta> emails = state.getMimeEntries(Email.CONTENT_ITEM_TYPE);
829 final Drawable emailDrawable = context.getDrawable(R.drawable.ic_email_24dp);
830 final String emailContentDescription = res.getString(R.string.header_email_entry);
831 if (emails != null) {
832 boolean isFirstEmailBound = true;
833 for (ValuesDelta email : emails) {
834 final String emailAddress = email.getEmailData();
835 if (TextUtils.isEmpty(emailAddress)) {
836 continue;
837 }
838 CharSequence emailType = null;
839 if (email.hasEmailType()) {
840 emailType = Email.getTypeLabel(
841 res, email.getEmailType(), email.getEmailLabel());
842 }
843 bindData(emailDrawable, emailContentDescription, emailAddress, emailType,
844 isFirstEmailBound);
845 isFirstEmailBound = false;
846 }
847 }
848
849 mKindSectionViews.setVisibility(mKindSectionViews.getChildCount() > 0 ? VISIBLE : GONE);
850 // Hide the "More fields" link
851 mMoreFields.setVisibility(GONE);
852 }
853
854 protected void updateAccountHeaderContentDescription() {
855 final StringBuilder builder = new StringBuilder();
856 builder.append(EditorUiUtils.getAccountInfoContentDescription(
857 mAccountHeaderName.getText(), mAccountHeaderType.getText()));
858 mAccountHeaderContainer.setContentDescription(builder);
859 }
860
861 private void bindData(Drawable icon, String iconContentDescription, CharSequence data,
862 CharSequence type, boolean isFirstEntry) {
863 bindData(icon, iconContentDescription, data, type, isFirstEntry, false);
864 }
865
866 private void bindData(Drawable icon, String iconContentDescription, CharSequence data,
867 CharSequence type, boolean isFirstEntry, boolean forceLTR) {
868 final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
869 Context.LAYOUT_INFLATER_SERVICE);
870 final View field = inflater.inflate(R.layout.item_read_only_field, mKindSectionViews,
871 false);
872 if (isFirstEntry) {
873 final ImageView imageView = (ImageView) field.findViewById(R.id.kind_icon);
874 imageView.setImageDrawable(icon);
875 imageView.setContentDescription(iconContentDescription);
876 } else {
877 final ImageView imageView = (ImageView) field.findViewById(R.id.kind_icon);
878 imageView.setVisibility(View.INVISIBLE);
879 imageView.setContentDescription(null);
880 }
881 final TextView dataView = (TextView) field.findViewById(R.id.data);
882 dataView.setText(data);
883 if (forceLTR) {
884 dataView.setTextDirection(View.TEXT_DIRECTION_LTR);
885 }
886 final TextView typeView = (TextView) field.findViewById(R.id.type);
887 if (!TextUtils.isEmpty(type)) {
888 typeView.setText(type);
889 } else {
890 typeView.setVisibility(View.GONE);
891 }
892 mKindSectionViews.addView(field);
Walter Jang9a552372016-08-24 11:51:05 -0700893 }
894
Gary Mai98868d32016-09-14 11:55:04 -0700895 private void addAccountInfo() {
Walter Jang82acd422015-10-17 14:01:27 -0700896 mAccountHeaderContainer.setVisibility(View.GONE);
Walter Jang82acd422015-10-17 14:01:27 -0700897 mRawContactContainer.setVisibility(View.GONE);
Gary Mai98868d32016-09-14 11:55:04 -0700898 final KindSectionData nameSectionData =
899 mKindSectionDataMap.get(StructuredName.CONTENT_ITEM_TYPE);
900 if (nameSectionData == null) return;
Walter Jang82acd422015-10-17 14:01:27 -0700901 final RawContactDelta rawContactDelta =
Gary Mai98868d32016-09-14 11:55:04 -0700902 nameSectionData.getRawContactDelta();
Walter Jang708ea9e2015-09-10 15:42:05 -0700903
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700904 final AccountDisplayInfo account =
905 mAccountDisplayInfoFactory.getAccountDisplayInfoFor(rawContactDelta);
906
Walter Jang708ea9e2015-09-10 15:42:05 -0700907 // Get the account information for the primary raw contact delta
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700908 final String accountLabel = mIsUserProfile
909 ? EditorUiUtils.getAccountHeaderLabelForMyProfile(getContext(), account)
910 : account.getNameLabel().toString();
Walter Jang708ea9e2015-09-10 15:42:05 -0700911
Walter Jang23709542015-10-22 12:50:58 -0700912 // Either the account header or selector should be shown, not both.
Walter Jang708ea9e2015-09-10 15:42:05 -0700913 final List<AccountWithDataSet> accounts =
914 AccountTypeManager.getInstance(getContext()).getAccounts(true);
Walter Jang82acd422015-10-17 14:01:27 -0700915 if (mHasNewContact && !mIsUserProfile) {
916 if (accounts.size() > 1) {
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700917 addAccountSelector(rawContactDelta, accountLabel);
Walter Jangbe5e1b12015-10-17 11:38:29 -0700918 } else {
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700919 addAccountHeader(accountLabel);
Walter Jangbe5e1b12015-10-17 11:38:29 -0700920 }
Gary Mai98868d32016-09-14 11:55:04 -0700921 } else if (mIsUserProfile || !shouldHideAccountContainer(mRawContactDeltas)) {
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700922 addAccountHeader(accountLabel);
Walter Jang708ea9e2015-09-10 15:42:05 -0700923 }
Walter Jang23709542015-10-22 12:50:58 -0700924
925 // The raw contact selector should only display linked raw contacts that can be edited in
926 // the full editor (i.e. they are not newly created raw contacts)
Tingting Wang2bb85d22015-10-23 13:01:09 -0700927 final RawContactAccountListAdapter adapter = new RawContactAccountListAdapter(getContext(),
Gary Mai98868d32016-09-14 11:55:04 -0700928 getRawContactDeltaListForSelector(mRawContactDeltas));
Tingting Wang2bb85d22015-10-23 13:01:09 -0700929 if (adapter.getCount() > 0) {
930 final String accountsSummary = getResources().getQuantityString(
931 R.plurals.compact_editor_linked_contacts_selector_title,
932 adapter.getCount(), adapter.getCount());
Walter Jang23709542015-10-22 12:50:58 -0700933 addRawContactAccountSelector(accountsSummary, adapter);
934 }
Walter Jang708ea9e2015-09-10 15:42:05 -0700935 }
936
Tingting Wang2bb85d22015-10-23 13:01:09 -0700937 private RawContactDeltaList getRawContactDeltaListForSelector(
938 RawContactDeltaList rawContactDeltas) {
939 // Sort raw contacts so google accounts come first
940 Collections.sort(rawContactDeltas, new RawContactDeltaComparator(getContext()));
941
942 final RawContactDeltaList result = new RawContactDeltaList();
Gary Mai98868d32016-09-14 11:55:04 -0700943 for (int i = 0; i < rawContactDeltas.size(); i++) {
944 final RawContactDelta rawContactDelta = rawContactDeltas.get(i);
Tingting Wang2bb85d22015-10-23 13:01:09 -0700945 if (rawContactDelta.isVisible() && rawContactDelta.getRawContactId() > 0) {
946 // Only add raw contacts that can be opened in the editor
947 result.add(rawContactDelta);
948 }
949 }
950 // Don't return a list of size 1 that would just open the raw contact being edited
951 // in the compact editor in the full editor
952 if (result.size() == 1 && result.get(0).getRawContactAccountType(
953 getContext()).areContactsWritable()) {
954 result.clear();
955 return result;
956 }
957 return result;
958 }
959
Tingting Wang1594c6f2015-10-26 17:39:16 -0700960 // Returns true if there are multiple writable rawcontacts and no read-only ones,
961 // or there are both writable and read-only rawcontacts.
962 private boolean shouldHideAccountContainer(RawContactDeltaList rawContactDeltas) {
Tingting Wang2bb85d22015-10-23 13:01:09 -0700963 int writable = 0;
964 int readonly = 0;
965 for (RawContactDelta rawContactDelta : rawContactDeltas) {
966 if (rawContactDelta.isVisible() && rawContactDelta.getRawContactId() > 0) {
967 if (rawContactDelta.getRawContactAccountType(getContext()).areContactsWritable()) {
968 writable++;
969 } else {
970 readonly++;
971 }
972 }
973 }
974 return (writable > 1 || (writable > 0 && readonly > 0));
975 }
976
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700977 private void addAccountHeader(String accountLabel) {
Walter Jang82acd422015-10-17 14:01:27 -0700978 mAccountHeaderContainer.setVisibility(View.VISIBLE);
979
Walter Jangbe5e1b12015-10-17 11:38:29 -0700980 // Set the account name
Walter Jangbe5e1b12015-10-17 11:38:29 -0700981 mAccountHeaderName.setVisibility(View.VISIBLE);
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700982 mAccountHeaderName.setText(accountLabel);
Walter Jangbe5e1b12015-10-17 11:38:29 -0700983
984 // Set the account type
985 final String selectorTitle = getResources().getString(
986 R.string.compact_editor_account_selector_title);
987 mAccountHeaderType.setText(selectorTitle);
988
989 // Set the icon
Gary Mai98868d32016-09-14 11:55:04 -0700990 final KindSectionData nameSectionData =
991 mKindSectionDataMap.get(StructuredName.CONTENT_ITEM_TYPE);
992 if (nameSectionData != null) {
Walter Jang82acd422015-10-17 14:01:27 -0700993 final RawContactDelta rawContactDelta =
Gary Mai98868d32016-09-14 11:55:04 -0700994 nameSectionData.getRawContactDelta();
Walter Jang82acd422015-10-17 14:01:27 -0700995 if (rawContactDelta != null) {
996 final AccountType accountType =
997 rawContactDelta.getRawContactAccountType(getContext());
998 mAccountHeaderIcon.setImageDrawable(accountType.getDisplayIcon(getContext()));
999 }
1000 }
Walter Jangbe5e1b12015-10-17 11:38:29 -07001001
1002 // Set the content description
1003 mAccountHeaderContainer.setContentDescription(
Marcus Hagerottfac695a2016-08-24 17:02:40 -07001004 EditorUiUtils.getAccountInfoContentDescription(accountLabel,
1005 selectorTitle));
Walter Jangbe5e1b12015-10-17 11:38:29 -07001006 }
1007
Marcus Hagerottfac695a2016-08-24 17:02:40 -07001008 private void addAccountSelector(final RawContactDelta rawContactDelta, CharSequence nameLabel) {
Gary Mai46cb3102016-08-10 18:14:09 -07001009 // Show save to default account.
Marcus Hagerottfac695a2016-08-24 17:02:40 -07001010 addAccountHeader(nameLabel.toString());
Gary Mai46cb3102016-08-10 18:14:09 -07001011 // Add handlers for choosing another account to save to.
1012 mAccountHeaderExpanderIcon.setVisibility(View.VISIBLE);
1013 mAccountHeaderContainer.setOnClickListener(new View.OnClickListener() {
Walter Jang708ea9e2015-09-10 15:42:05 -07001014 @Override
1015 public void onClick(View v) {
1016 final ListPopupWindow popup = new ListPopupWindow(getContext(), null);
1017 final AccountsListAdapter adapter =
1018 new AccountsListAdapter(getContext(),
1019 AccountsListAdapter.AccountListFilter.ACCOUNTS_CONTACT_WRITABLE,
1020 mPrimaryAccount);
Gary Mai46cb3102016-08-10 18:14:09 -07001021 popup.setWidth(mAccountHeaderContainer.getWidth());
1022 popup.setAnchorView(mAccountHeaderContainer);
Walter Jang708ea9e2015-09-10 15:42:05 -07001023 popup.setAdapter(adapter);
1024 popup.setModal(true);
1025 popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
1026 popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
1027 @Override
1028 public void onItemClick(AdapterView<?> parent, View view, int position,
1029 long id) {
1030 UiClosables.closeQuietly(popup);
1031 final AccountWithDataSet newAccount = adapter.getItem(position);
1032 if (mListener != null && !mPrimaryAccount.equals(newAccount)) {
1033 mListener.onRebindEditorsForNewContact(
Walter Jang82acd422015-10-17 14:01:27 -07001034 rawContactDelta,
Walter Jang708ea9e2015-09-10 15:42:05 -07001035 mPrimaryAccount,
1036 newAccount);
1037 }
1038 }
1039 });
1040 popup.show();
1041 }
1042 });
1043 }
1044
Walter Jang23709542015-10-22 12:50:58 -07001045 private void addRawContactAccountSelector(String accountsSummary,
1046 final RawContactAccountListAdapter adapter) {
Tingting Wang655ad1a2015-10-05 17:51:14 -07001047 mRawContactContainer.setVisibility(View.VISIBLE);
1048
Tingting Wang655ad1a2015-10-05 17:51:14 -07001049 mRawContactSummary.setText(accountsSummary);
Tingting Wang655ad1a2015-10-05 17:51:14 -07001050
1051 mRawContactContainer.setOnClickListener(new View.OnClickListener() {
1052 @Override
1053 public void onClick(View v) {
1054 final ListPopupWindow popup = new ListPopupWindow(getContext(), null);
Tingting Wang655ad1a2015-10-05 17:51:14 -07001055 popup.setWidth(mRawContactContainer.getWidth());
1056 popup.setAnchorView(mRawContactContainer);
1057 popup.setAdapter(adapter);
1058 popup.setModal(true);
1059 popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
1060 popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
1061 @Override
1062 public void onItemClick(AdapterView<?> parent, View view, int position,
1063 long id) {
1064 UiClosables.closeQuietly(popup);
Tingting Wang655ad1a2015-10-05 17:51:14 -07001065
1066 if (mListener != null) {
Tingting Wang91cee282015-10-07 13:48:17 -07001067 final long rawContactId = adapter.getItemId(position);
1068 final Uri rawContactUri = ContentUris.withAppendedId(
1069 ContactsContract.RawContacts.CONTENT_URI, rawContactId);
1070 final RawContactDelta rawContactDelta = adapter.getItem(position);
1071 final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
1072 getContext());
1073 final AccountType accountType = rawContactDelta.getAccountType(
1074 accountTypes);
1075 final boolean isReadOnly = !accountType.areContactsWritable();
1076
1077 mListener.onRawContactSelected(rawContactUri, rawContactId, isReadOnly);
Tingting Wang655ad1a2015-10-05 17:51:14 -07001078 }
1079 }
1080 });
1081 popup.show();
1082 }
1083 });
1084 }
1085
Walter Jang363d3fd2015-09-16 10:29:07 -07001086 private void addPhotoView() {
Gary Mai98868d32016-09-14 11:55:04 -07001087 // Get the kind section data and values delta that we will display in the photo view. Either
1088 // the aggregate photo or the photo from the raw contact that is being edited.
1089 final Pair<KindSectionData, ValuesDelta> photo =
1090 mPhotoKindSectionDataList.getEntryToDisplay(
1091 mRawContactIdToDisplayAlone > 0
1092 ? mRawContactIdToDisplayAlone
1093 : mAggregatePhotoId);
1094 if (photo == null) {
Walter Jang3e5ae0d2015-09-20 12:43:37 -07001095 wlog("photo: no kind section data parsed");
Walter Jangcbd431d2015-10-06 13:07:30 -07001096 mPhotoView.setVisibility(View.GONE);
Walter Jang363d3fd2015-09-16 10:29:07 -07001097 return;
Marcus Hagerottcf7f2952016-09-06 13:49:17 -07001098 } else {
1099 mPhotoView.setVisibility(View.VISIBLE);
Walter Jang363d3fd2015-09-16 10:29:07 -07001100 }
Walter Jang06f73a12015-06-17 11:15:48 -07001101
Walter Jang31a74ad2015-10-02 19:17:39 -07001102 // Set the photo view
Gary Mai98868d32016-09-14 11:55:04 -07001103 mPhotoView.setPhoto(photo.second, mMaterialPalette);
Walter Jang31a74ad2015-10-02 19:17:39 -07001104
Gary Mai98868d32016-09-14 11:55:04 -07001105 // If we're showing an aggregate photo, set it to read only.
1106 if (mRawContactIdToDisplayAlone < 1) {
Walter Jang31a74ad2015-10-02 19:17:39 -07001107 mPhotoView.setReadOnly(true);
1108 return;
1109 }
Walter Jang31a74ad2015-10-02 19:17:39 -07001110 mPhotoView.setReadOnly(false);
Gary Mai98868d32016-09-14 11:55:04 -07001111 mPhotoRawContactId = photo.first.getRawContactDelta().getRawContactId();
1112 mPhotoValuesDelta = photo.second;
Walter Jang31a74ad2015-10-02 19:17:39 -07001113 }
1114
Walter Jangf5dfea42015-09-16 12:30:36 -07001115 private void addKindSectionViews() {
Walter Jang3e5ae0d2015-09-20 12:43:37 -07001116 int i = -1;
Gary Mai98868d32016-09-14 11:55:04 -07001117
1118 for (String mimeType : mSortedMimetypes) {
Walter Jang3e5ae0d2015-09-20 12:43:37 -07001119 i++;
Gary Mai98868d32016-09-14 11:55:04 -07001120 final CompactKindSectionView kindSectionView;
1121 // TODO: Since we don't have a primary name kind anymore, refactor and collapse
1122 // these two branches and the following code paths.
Tingting Wangf695eb32015-10-15 18:45:15 -07001123 if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
Gary Mai98868d32016-09-14 11:55:04 -07001124 final KindSectionData nameSectionData = mKindSectionDataMap.get(mimeType);
1125 if (nameSectionData == null) {
Walter Jang82acd422015-10-17 14:01:27 -07001126 vlog("kind: " + i + " " + mimeType + " dropped");
1127 continue;
Tingting Wangf695eb32015-10-15 18:45:15 -07001128 }
Walter Jang82acd422015-10-17 14:01:27 -07001129 vlog("kind: " + i + " " + mimeType + " using first entry only");
Gary Mai98868d32016-09-14 11:55:04 -07001130 kindSectionView = inflateKindSectionView(
1131 mKindSectionViews, nameSectionData, mimeType,
1132 nameSectionData.getValuesDeltas().get(0));
Walter Jang82acd422015-10-17 14:01:27 -07001133 } else {
Gary Mai98868d32016-09-14 11:55:04 -07001134 final KindSectionData kindSectionData = mKindSectionDataMap.get(mimeType);
Walter Jang82acd422015-10-17 14:01:27 -07001135
1136 // Ignore mime types that we've already handled
1137 if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
1138 vlog("kind: " + i + " " + mimeType + " dropped");
1139 continue;
1140 }
Gary Mai98868d32016-09-14 11:55:04 -07001141 kindSectionView = inflateKindSectionView(
1142 mKindSectionViews, kindSectionData, mimeType,
1143 /* primaryValueDelta =*/ null);
Walter Jangcab3dce2015-02-09 17:48:03 -08001144 }
Gary Mai98868d32016-09-14 11:55:04 -07001145 mKindSectionViews.addView(kindSectionView);
Walter Jangcab3dce2015-02-09 17:48:03 -08001146
Gary Mai98868d32016-09-14 11:55:04 -07001147 // Keep a pointer to the KindSectionView for each mimeType
1148 mKindSectionViewMap.put(mimeType, kindSectionView);
Walter Jangf10ca152015-09-22 15:23:55 -07001149 }
Walter Jangf10ca152015-09-22 15:23:55 -07001150 }
1151
Walter Jangf5dfea42015-09-16 12:30:36 -07001152 private CompactKindSectionView inflateKindSectionView(ViewGroup viewGroup,
Gary Mai98868d32016-09-14 11:55:04 -07001153 KindSectionData kindSectionData, String mimeType,
Walter Jang82acd422015-10-17 14:01:27 -07001154 ValuesDelta primaryValuesDelta) {
Walter Jangf5dfea42015-09-16 12:30:36 -07001155 final CompactKindSectionView kindSectionView = (CompactKindSectionView)
1156 mLayoutInflater.inflate(R.layout.compact_item_kind_section, viewGroup,
1157 /* attachToRoot =*/ false);
Walter Jang45b86d52015-10-15 15:23:16 -07001158 kindSectionView.setIsUserProfile(mIsUserProfile);
Walter Jangf5dfea42015-09-16 12:30:36 -07001159
Walter Jang192a01c2015-09-22 15:23:55 -07001160 if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)
Walter Jangf5dfea42015-09-16 12:30:36 -07001161 || Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jang192a01c2015-09-22 15:23:55 -07001162 // Phone numbers and email addresses are always displayed,
1163 // even if they are empty
Walter Jangf5dfea42015-09-16 12:30:36 -07001164 kindSectionView.setHideWhenEmpty(false);
1165 }
Walter Jangf5dfea42015-09-16 12:30:36 -07001166
Walter Jang192a01c2015-09-22 15:23:55 -07001167 // Since phone numbers and email addresses displayed even if they are empty,
1168 // they will be the only types you add new values to initially for new contacts
1169 kindSectionView.setShowOneEmptyEditor(true);
1170
Gary Mai98868d32016-09-14 11:55:04 -07001171 kindSectionView.setState(kindSectionData, mViewIdGenerator, mListener,
Walter Jang82acd422015-10-17 14:01:27 -07001172 primaryValuesDelta);
Walter Jangf5dfea42015-09-16 12:30:36 -07001173
1174 return kindSectionView;
Walter Jangcab3dce2015-02-09 17:48:03 -08001175 }
1176
Walter Jange3945952015-10-27 12:44:54 -07001177 void maybeSetReadOnlyDisplayNameAsPrimary(String readOnlyDisplayName) {
1178 if (TextUtils.isEmpty(readOnlyDisplayName)) return;
1179 final CompactKindSectionView primaryNameKindSectionView = getPrimaryNameKindSectionView();
1180 if (primaryNameKindSectionView != null && primaryNameKindSectionView.isEmptyName()) {
1181 vlog("name: using read only display name as primary name");
1182 primaryNameKindSectionView.setName(readOnlyDisplayName);
1183 }
1184 }
1185
1186 private CompactKindSectionView getPrimaryNameKindSectionView() {
Gary Mai98868d32016-09-14 11:55:04 -07001187 return mKindSectionViewMap.get(StructuredName.CONTENT_ITEM_TYPE);
Walter Jang4f5594a2015-10-06 18:40:31 -07001188 }
1189
Walter Jangd6753152015-10-02 09:23:13 -07001190 private void showAllFields() {
Walter Jang79658e12015-09-24 10:36:26 -07001191 // Stop hiding empty editors and allow the user to enter values for all kinds now
1192 for (int i = 0; i < mKindSectionViews.getChildCount(); i++) {
1193 final CompactKindSectionView kindSectionView =
1194 (CompactKindSectionView) mKindSectionViews.getChildAt(i);
1195 kindSectionView.setHideWhenEmpty(false);
1196 kindSectionView.updateEmptyEditors(/* shouldAnimate =*/ true);
1197 }
1198 mIsExpanded = true;
Walter Jang79658e12015-09-24 10:36:26 -07001199
Walter Jangf5dfea42015-09-16 12:30:36 -07001200 // Hide the more fields button
1201 mMoreFields.setVisibility(View.GONE);
Walter Jangcab3dce2015-02-09 17:48:03 -08001202 }
1203
Marcus Hagerottcf7f2952016-09-06 13:49:17 -07001204 private boolean hasMoreFields() {
Gary Mai98868d32016-09-14 11:55:04 -07001205 for (CompactKindSectionView section : mKindSectionViewMap.values()) {
1206 if (section.getVisibility() != View.VISIBLE) {
1207 return true;
Marcus Hagerottcf7f2952016-09-06 13:49:17 -07001208 }
1209 }
1210 return false;
1211 }
1212
Walter Jangbf63a6d2015-05-05 09:14:35 -07001213 private static void vlog(String message) {
1214 if (Log.isLoggable(TAG, Log.VERBOSE)) {
1215 Log.v(TAG, message);
Walter Jangcab3dce2015-02-09 17:48:03 -08001216 }
1217 }
Walter Jang363d3fd2015-09-16 10:29:07 -07001218
1219 private static void wlog(String message) {
1220 if (Log.isLoggable(TAG, Log.WARN)) {
1221 Log.w(TAG, message);
1222 }
1223 }
1224
1225 private static void elog(String message) {
1226 Log.e(TAG, message);
1227 }
Walter Jangcab3dce2015-02-09 17:48:03 -08001228}