ContactEditorFragment.java revision b55107303cc46906c265582a8931172f13d684b6
1cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann/* 2ef3f8f045ed4150caa64749742227acd0e6b85d8Daniel Lehmann * Copyright (C) 2010 The Android Open Source Project 3cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * 4cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * you may not use this file except in compliance with the License. 6cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * You may obtain a copy of the License at 7cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * 8cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * 10cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Unless required by applicable law or agreed to in writing, software 11cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * See the License for the specific language governing permissions and 14cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * limitations under the License 15cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 16cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor; 18cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 19cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity; 20bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.AlertDialog; 21bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.Dialog; 22bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.DialogFragment; 23cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 24cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 25bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface; 26cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 27f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 28cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 29cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 3091004b37683c15650eccde68ff04defcf94a1c84Maurice Chuimport android.provider.ContactsContract.CommonDataKinds.Photo; 31f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 32688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Leeimport android.text.TextUtils; 33cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 34cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 35cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 36cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 37d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.AdapterView; 386c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener; 396c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.BaseAdapter; 4080d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 41d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.ListPopupWindow; 42cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast; 43cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 44e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactSaveService; 45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 46e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ContactEditorActivity; 473f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor; 4844cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.AccountTypeManager; 4992101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContactDelta; 5092101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContactDeltaList; 5192101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContactModifier; 5244cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.ValuesDelta; 5344cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.AccountType; 5444cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.AccountWithDataSet; 5544cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.util.AccountsListAdapter; 5644cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.util.AccountsListAdapter.AccountListFilter; 57e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.PhotoSelectionHandler; 58e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; 59e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.Editor.EditorListener; 60c3d202ccbaf93ddd8291672027e59f549c32eee3Brian Attwellimport com.android.contacts.list.UiIntentActions; 61e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ContactPhotoUtils; 6286625158bdc52855c37e96bf098ba7a213c810d7Chiao Chengimport com.android.contacts.util.UiClosables; 6392101e77238e450dedb56814cec80edc0adf79c0Walter Jang 64851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.google.common.collect.ImmutableList; 6544cfc56d1701629070384364416c1311b780535dChiao Chengimport com.google.common.collect.Lists; 66e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 67637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Leeimport java.io.FileNotFoundException; 68f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections; 69daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwellimport java.util.HashMap; 70f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List; 71f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 723f990ba4e35a99078d831c041290e574a320caa5Walter Jang/** 733f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Contact editor with all fields displayed. 743f990ba4e35a99078d831c041290e574a320caa5Walter Jang */ 753f990ba4e35a99078d831c041290e574a320caa5Walter Jangpublic class ContactEditorFragment extends ContactEditorBaseFragment implements 763f990ba4e35a99078d831c041290e574a320caa5Walter Jang ContactEditor, SplitContactConfirmationDialogFragment.Listener, 77fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener, 782b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann RawContactReadOnlyEditorView.Listener { 79cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 80cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Joins 81cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin"; 82cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin"; 83cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 84daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell private static final String KEY_EXPANDED_EDITORS = "expandedEditors"; 85f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 86cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Photos 87cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester"; 88cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CURRENT_PHOTO_URI = "currentphotouri"; 89cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_UPDATED_PHOTOS = "updatedPhotos"; 90cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 91cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Aggregations 92cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID = 93cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang "aggregationSuggestionsRawContactId"; 94cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 95a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public static final String SAVE_MODE_EXTRA_KEY = "saveMode"; 96a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 97fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 98fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Helpers 99fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 100fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private AggregationSuggestionEngine mAggregationSuggestionEngine; 101cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 102fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 103fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Contact editor state 104fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 105fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Joins 106fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private long mContactIdForJoin; 107fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mContactWritableForJoin; 108fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 109fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Used to store which raw contact editors have been expanded. Keyed on raw contact ids. 110fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private HashMap<Long, Boolean> mExpandedEditors = new HashMap<Long, Boolean>(); 111fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 112fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Photos 113fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang /** 114fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * The raw contact for which we started "take photo" or "choose photo from gallery" most 115fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * recently. Used to restore {@link #mCurrentPhotoHandler} after orientation change. 116fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang */ 117fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private long mRawContactIdRequestingPhoto; 11844cfc56d1701629070384364416c1311b780535dChiao Cheng 119fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang /** 120fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * The {@link PhotoHandler} for the photo editor for the {@link #mRawContactIdRequestingPhoto} 121fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * raw contact. 122fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * 123fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * A {@link PhotoHandler} is created for each photo editor in {@link #bindPhotoHandler}, but 124fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * the only "active" one should get the activity result. This member represents the active 125fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * one. 126fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang */ 127fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private PhotoHandler mCurrentPhotoHandler; 128fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Uri mCurrentPhotoUri; 129fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Bundle mUpdatedPhotos = new Bundle(); 130daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 131fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Aggregations 1329302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private long mAggregationSuggestionsRawContactId; 1339302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private View mAggregationSuggestionView; 1346c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private ListPopupWindow mAggregationSuggestionPopup; 1356c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1366c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private static final class AggregationSuggestionAdapter extends BaseAdapter { 1376c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final Activity mActivity; 1386c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final boolean mSetNewContact; 1396c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final AggregationSuggestionView.Listener mListener; 1406c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final List<Suggestion> mSuggestions; 1416c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1426c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public AggregationSuggestionAdapter(Activity activity, boolean setNewContact, 1436c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) { 1446c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mActivity = activity; 1456c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSetNewContact = setNewContact; 1466c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mListener = listener; 1476c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSuggestions = suggestions; 1486c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1496c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1506c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 1516c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 1526c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa Suggestion suggestion = (Suggestion) getItem(position); 1536c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa LayoutInflater inflater = mActivity.getLayoutInflater(); 1546c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView suggestionView = 1556c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (AggregationSuggestionView) inflater.inflate( 1566c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa R.layout.aggregation_suggestions_item, null); 1576c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setNewContact(mSetNewContact); 1586c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setListener(mListener); 1596c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.bindSuggestion(suggestion); 1606c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return suggestionView; 1616c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1626c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1636c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 1646c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public long getItemId(int position) { 1656c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return position; 1666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1676c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1686c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 1696c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public Object getItem(int position) { 1706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.get(position); 1716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1726c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1736c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 1746c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public int getCount() { 1756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.size(); 1766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 1796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private OnItemClickListener mAggregationSuggestionItemClickListener = 1806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new OnItemClickListener() { 1816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 1826c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 1836c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view; 1846c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.handleItemClickEvent(); 18586625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 1866c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = null; 1876c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 1886c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa }; 1896c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 190cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 191cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 192cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 193b55107303cc46906c265582a8931172f13d684b6Walter Jang 194b55107303cc46906c265582a8931172f13d684b6Walter Jang @Override 195b55107303cc46906c265582a8931172f13d684b6Walter Jang protected void setEnabled(boolean enabled) { 196b55107303cc46906c265582a8931172f13d684b6Walter Jang if (mContent != null) { 197b55107303cc46906c265582a8931172f13d684b6Walter Jang int count = mContent.getChildCount(); 198b55107303cc46906c265582a8931172f13d684b6Walter Jang for (int i = 0; i < count; i++) { 199b55107303cc46906c265582a8931172f13d684b6Walter Jang mContent.getChildAt(i).setEnabled(enabled); 20002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 20102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 202b55107303cc46906c265582a8931172f13d684b6Walter Jang setAggregationSuggestionViewEnabled(enabled); 203b55107303cc46906c265582a8931172f13d684b6Walter Jang final Activity activity = getActivity(); 204b55107303cc46906c265582a8931172f13d684b6Walter Jang if (activity != null) activity.invalidateOptionsMenu(); 20502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 20602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 207cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 208f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onStop() { 209f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super.onStop(); 21086625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng 21186625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 21286625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng 213825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If anything was left unsaved, save it now but keep the editor open. 214f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) { 215623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann save(SaveMode.RELOAD); 216825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 217f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 218f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 219f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 22036184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee public void onDestroy() { 22136184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee super.onDestroy(); 22236184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee if (mAggregationSuggestionEngine != null) { 22336184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee mAggregationSuggestionEngine.quit(); 22436184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee } 22536184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee } 22636184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee 22736184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee @Override 228cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 229cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 230cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 231f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 232e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 2333648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 234cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 235cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 236cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 237cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 238222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 239e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onStart() { 240e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener); 241e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov super.onStart(); 242e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 243e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 2443f990ba4e35a99078d831c041290e574a320caa5Walter Jang @Override 245f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 246f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 247f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 248ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang if (savedState != null) { 249cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Joins 250cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 251cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN); 252cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 253daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell mExpandedEditors = (HashMap<Long, Boolean>) 254daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell savedState.getSerializable(KEY_EXPANDED_EDITORS); 255cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 256cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Photos 257cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mRawContactIdRequestingPhoto = savedState.getLong( 258cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 259cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mCurrentPhotoUri = savedState.getParcelable(KEY_CURRENT_PHOTO_URI); 260cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS); 261cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 262cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Aggregations 263cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mAggregationSuggestionsRawContactId = savedState.getLong( 264cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID); 26544cfc56d1701629070384364416c1311b780535dChiao Cheng } 266fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 267fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 268fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov @Override 2692b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public void onExternalEditorRequest(AccountWithDataSet account, Uri uri) { 270fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(account, uri, null, false); 271fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 272fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 273daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell @Override 274daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell public void onEditorExpansionChanged() { 275daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell updatedExpandedEditorsMap(); 276daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 277daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 278ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang @Override 2791ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov public void setIntentExtras(Bundle extras) { 2801ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov if (extras == null || extras.size() == 0) { 2811ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov return; 282bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 283916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 284a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 285851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContactDelta state : mState) { 286851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = state.getAccountType(accountTypes); 28796e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 2881ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov // Apply extras to the first writable raw contact only 289851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.parseExtras(mContext, type, state, extras); 2901ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov break; 2911ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 2921ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 293f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 294cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 295d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 296d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Removes a current editor ({@link #mState}) and rebinds new editor for a new account. 297d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Some of old data are reused with new restriction enforced by the new account. 298d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 2992b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro * @param oldState Old data being edited. 300d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param oldAccount Old account associated with oldState. 301d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param newAccount New account to be used. 302d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 303d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void rebindEditorsForNewContact( 304851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta oldState, AccountWithDataSet oldAccount, 305851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu AccountWithDataSet newAccount) { 306d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 30767e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner AccountType oldAccountType = accountTypes.getAccountTypeForAccount(oldAccount); 30867e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner AccountType newAccountType = accountTypes.getAccountTypeForAccount(newAccount); 309d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 310d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccountType.getCreateContactActivityClassName() != null) { 311d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa Log.w(TAG, "external activity called in rebind situation"); 312d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (mListener != null) { 313d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras); 314d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 315d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 31644cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = false; 31744cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = false; 31844cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 319b55107303cc46906c265582a8931172f13d684b6Walter Jang setStateForNewContact(newAccount, newAccountType, oldState, oldAccountType); 32044cfc56d1701629070384364416c1311b780535dChiao Cheng if (mIsEdit) { 321b55107303cc46906c265582a8931172f13d684b6Walter Jang setStateForExistingContact(mDefaultDisplayName, mIsUserProfile, mRawContacts); 32244cfc56d1701629070384364416c1311b780535dChiao Cheng } 323d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 324d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 325d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 326ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang @Override 327ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang protected void bindEditors() { 3285671c7e7718c3285dc0391807401083986fcfd51Maurice Chu // bindEditors() can only bind views if there is data in mState, so immediately return 3295671c7e7718c3285dc0391807401083986fcfd51Maurice Chu // if mState is null 33044cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 33144cfc56d1701629070384364416c1311b780535dChiao Cheng return; 33244cfc56d1701629070384364416c1311b780535dChiao Cheng } 33344cfc56d1701629070384364416c1311b780535dChiao Cheng 33444cfc56d1701629070384364416c1311b780535dChiao Cheng // Check if delta list is ready. Delta list is populated from existing data and when 33544cfc56d1701629070384364416c1311b780535dChiao Cheng // editing an read-only contact, it's also populated with newly created data for the 33644cfc56d1701629070384364416c1311b780535dChiao Cheng // blank form. When the data is not ready, skip. This method will be called multiple times. 33744cfc56d1701629070384364416c1311b780535dChiao Cheng if ((mIsEdit && !mExistingContactDataReady) || (mHasNewContact && !mNewContactDataReady)) { 3385671c7e7718c3285dc0391807401083986fcfd51Maurice Chu return; 3395671c7e7718c3285dc0391807401083986fcfd51Maurice Chu } 3405671c7e7718c3285dc0391807401083986fcfd51Maurice Chu 341f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 342f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 343cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 344f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 345f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 346cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 347f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 348f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 349a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 350a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan int numRawContacts = mState.size(); 35144cfc56d1701629070384364416c1311b780535dChiao Cheng 352a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan for (int i = 0; i < numRawContacts; i++) { 353f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 354851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta rawContactDelta = mState.get(i); 355851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (!rawContactDelta.isVisible()) continue; 356f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 357851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = rawContactDelta.getAccountType(accountTypes); 358851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long rawContactId = rawContactDelta.getRawContactId(); 359f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 36072af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor; 3612b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (!type.areContactsWritable()) { 362fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov editor = (BaseRawContactEditorView) inflater.inflate( 3632b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann R.layout.raw_contact_readonly_editor_view, mContent, false); 364fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 365fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view, 366fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mContent, false); 367cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 368daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setListener(this); 369daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(mContext) 370daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell .getAccounts(true); 371daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (mHasNewContact && !mNewLocalProfile && accounts.size() > 1) { 372daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell addAccountSwitcher(mState.get(0), editor); 373d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 374a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan 375b55107303cc46906c265582a8931172f13d684b6Walter Jang editor.setEnabled(isEnabled()); 376cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 377daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (mExpandedEditors.containsKey(rawContactId)) { 378daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setCollapsed(mExpandedEditors.get(rawContactId)); 379daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } else { 380daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell // By default, only the first editor will be expanded. 381daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setCollapsed(i != 0); 382daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 383daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 384f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 3857d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 386851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile()); 387daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setCollapsible(numRawContacts > 1); 388f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 3896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set up the photo handler. 3906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro bindPhotoHandler(editor, type, mState); 3916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 392c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell // If a new photo was chosen but not yet saved, we need to update the UI to 393c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell // reflect this. 394c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell final Uri photoUri = updatedPhotoUriForRawContact(rawContactId); 395c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell if (photoUri != null) editor.setFullSizedPhoto(photoUri); 39628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 39772af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (editor instanceof RawContactEditorView) { 3982828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki final Activity activity = getActivity(); 39972af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final RawContactEditorView rawContactEditor = (RawContactEditorView) editor; 4005ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov EditorListener listener = new EditorListener() { 401f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 402f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 403f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onRequest(int request) { 4042828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki if (activity.isFinishing()) { // Make sure activity is still running. 4052828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki return; 4062828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki } 4072bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) { 4082828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki acquireAggregationSuggestions(activity, rawContactEditor); 409d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell } else if (request == EditorListener.EDITOR_FOCUS_CHANGED) { 410d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell adjustNameFieldsHintDarkness(rawContactEditor); 41111bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 412f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 413f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 414f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 4152293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor removedEditor) { 416f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 4175ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov }; 4185ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov 41944cfc56d1701629070384364416c1311b780535dChiao Cheng final StructuredNameEditorView nameEditor = rawContactEditor.getNameEditor(); 4205ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov if (mRequestFocus) { 4215ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.requestFocus(); 4225ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov mRequestFocus = false; 4235ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov } 4245ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.setEditorListener(listener); 425688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee if (!TextUtils.isEmpty(mDefaultDisplayName)) { 426688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee nameEditor.setDisplayName(mDefaultDisplayName); 427688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee } 428f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 4295ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView phoneticNameEditor = 4305ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov rawContactEditor.getPhoneticNameEditor(); 4315ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov phoneticNameEditor.setEditorListener(listener); 4327d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup); 4337d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 434d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell final TextFieldsEditorView nickNameEditor = 435d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getNickNameEditor(); 436d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell nickNameEditor.setEditorListener(listener); 437d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell 4389302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactId == mAggregationSuggestionsRawContactId) { 4392828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki acquireAggregationSuggestions(activity, rawContactEditor); 440f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 441d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell 442d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell adjustNameFieldsHintDarkness(rawContactEditor); 443f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 444cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 445f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 446eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = false; 447eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 448b55107303cc46906c265582a8931172f13d684b6Walter Jang setGroupMetaData(); 449e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 450f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 451f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 452a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 453a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann // Refresh Action Bar as the visibility of the join command 454825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Activity can be null if we have been detached from the Activity 455825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann final Activity activity = getActivity(); 456825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (activity != null) activity.invalidateOptionsMenu(); 457daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 458daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell updatedExpandedEditorsMap(); 459daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 460daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 461daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell /** 462d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell * Adjust how dark the hint text should be on all the names' text fields. 463d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell * 464d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell * @param rawContactEditor editor to update 465d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell */ 466d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell private void adjustNameFieldsHintDarkness(RawContactEditorView rawContactEditor) { 467d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell // Check whether fields contain focus by calling findFocus() instead of hasFocus(). 468d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell // The hasFocus() value is not necessarily up to date. 469d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell final boolean nameFieldsAreNotFocused 470d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell = rawContactEditor.getNameEditor().findFocus() == null 471d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell && rawContactEditor.getPhoneticNameEditor().findFocus() == null 472d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell && rawContactEditor.getNickNameEditor().findFocus() == null; 473d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getNameEditor().setHintColorDark(!nameFieldsAreNotFocused); 474d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getPhoneticNameEditor().setHintColorDark(!nameFieldsAreNotFocused); 475d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getNickNameEditor().setHintColorDark(!nameFieldsAreNotFocused); 476d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell } 477d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell 478d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell /** 479daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell * Update the values in {@link #mExpandedEditors}. 480daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell */ 481daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell private void updatedExpandedEditorsMap() { 482daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell for (int i = 0; i < mContent.getChildCount(); i++) { 483daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell final View childView = mContent.getChildAt(i); 484daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (childView instanceof BaseRawContactEditorView) { 485daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell BaseRawContactEditorView childEditor = (BaseRawContactEditorView) childView; 486daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell mExpandedEditors.put(childEditor.getRawContactId(), childEditor.isCollapsed()); 487daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 488daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 4896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 490eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 49128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus /** 492c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell * If we've stashed a temporary file containing a contact's new photo, return its URI. 49328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * @param rawContactId identifies the raw-contact whose Bitmap we'll try to return. 494c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell * @return Uru of photo for specified raw-contact, or null 495c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell */ 496c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell private Uri updatedPhotoUriForRawContact(long rawContactId) { 497c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell return (Uri) mUpdatedPhotos.get(String.valueOf(rawContactId)); 49828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus } 49928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 5006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type, 501851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state) { 5026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final int mode; 5037e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell final boolean showIsPrimaryOption; 5046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (type.areContactsWritable()) { 5056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (editor.hasSetPhoto()) { 5067e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell mode = PhotoActionPopup.Modes.WRITE_ABLE_PHOTO; 5077e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell showIsPrimaryOption = hasMoreThanOnePhoto(); 5086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 509ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.NO_PHOTO; 5107e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell showIsPrimaryOption = false; 5116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 5127e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } else if (editor.hasSetPhoto() && hasMoreThanOnePhoto()) { 5137e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell mode = PhotoActionPopup.Modes.READ_ONLY_PHOTO; 5147e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell showIsPrimaryOption = true; 5156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 5167e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell // Read-only and either no photo or the only photo ==> no options 5177e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell editor.getPhotoEditor().setEditorListener(null); 5187e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell editor.getPhotoEditor().setShowPrimary(false); 5197e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell return; 5206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 52191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final PhotoHandler photoHandler = new PhotoHandler(mContext, editor, mode, state); 5226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro editor.getPhotoEditor().setEditorListener( 52391004b37683c15650eccde68ff04defcf94a1c84Maurice Chu (PhotoHandler.PhotoEditorListener) photoHandler.getListener()); 5247e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell editor.getPhotoEditor().setShowPrimary(showIsPrimaryOption); 5254bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki 5264bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki // Note a newly created raw contact gets some random negative ID, so any value is valid 5274bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki // here. (i.e. don't check against -1 or anything.) 5284bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki if (mRawContactIdRequestingPhoto == editor.getRawContactId()) { 5294bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mCurrentPhotoHandler = photoHandler; 5304bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki } 531cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 532cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 5330353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void saveDefaultAccountIfNecessary() { 5340353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Verify that this is a newly created contact, that the contact is composed of only 5350353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // 1 raw contact, and that the contact is not a user profile. 5360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (!Intent.ACTION_INSERT.equals(mAction) && mState.size() == 1 && 5370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan !isEditingUserProfile()) { 5380353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 5390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 5400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 5410353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Find the associated account for this contact (retrieve it here because there are 5420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // multiple paths to creating a contact and this ensures we always have the correct 5430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // account). 544851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta rawContactDelta = mState.get(0); 545851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String name = rawContactDelta.getAccountName(); 546851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String type = rawContactDelta.getAccountType(); 547851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String dataSet = rawContactDelta.getDataSet(); 5480353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 5490353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet account = (name == null || type == null) ? null : 5500353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan new AccountWithDataSet(name, type, dataSet); 5510353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils.saveDefaultAndAllAccounts(account); 5520353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 5530353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 554d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void addAccountSwitcher( 555851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta currentState, BaseRawContactEditorView editor) { 5562b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountWithDataSet currentAccount = new AccountWithDataSet( 557851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getAccountName(), 558851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getAccountType(), 559851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getDataSet()); 560d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final View accountView = editor.findViewById(R.id.account); 561daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell final View anchorView = editor.findViewById(R.id.account_selector_container); 562daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (accountView == null) { 563daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell return; 564daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 565daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell anchorView.setVisibility(View.VISIBLE); 566d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa accountView.setOnClickListener(new View.OnClickListener() { 567d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 568d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onClick(View v) { 569d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final ListPopupWindow popup = new ListPopupWindow(mContext, null); 570a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa final AccountsListAdapter adapter = 5716f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki new AccountsListAdapter(mContext, 5726f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, currentAccount); 573d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setWidth(anchorView.getWidth()); 574d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAnchorView(anchorView); 575d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAdapter(adapter); 576d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setModal(true); 577d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 578d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setOnItemClickListener(new AdapterView.OnItemClickListener() { 579d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 580d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, 581d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa long id) { 58286625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(popup); 5832b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountWithDataSet newAccount = adapter.getItem(position); 584d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (!newAccount.equals(currentAccount)) { 585d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa rebindEditorsForNewContact(currentState, currentAccount, newAccount); 586d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 587d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 588d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 589d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.show(); 590d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 591d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 592d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 593d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 594b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 595b55107303cc46906c265582a8931172f13d684b6Walter Jang protected boolean doSaveAction(int saveMode) { 5960353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Store account as default account, only if this is a new contact 5970353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan saveDefaultAccountIfNecessary(); 5980353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 5990353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Save contact 600ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState, 601ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(), 602ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus ((Activity)mContext).getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED, 603ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus mUpdatedPhotos); 604ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus mContext.startService(intent); 60587270e1b58e669354bb1571ced686421c56deb7aJosh Gargus 60687270e1b58e669354bb1571ced686421c56deb7aJosh Gargus // Don't try to save the same photos twice. 60787270e1b58e669354bb1571ced686421c56deb7aJosh Gargus mUpdatedPhotos = new Bundle(); 60887270e1b58e669354bb1571ced686421c56deb7aJosh Gargus 609f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 610f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 611f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 612ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang @Override 6132b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov public void onJoinCompleted(Uri uri) { 61436d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri); 6152b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov } 6162b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov 617ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang @Override 61836d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, 61936d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro Uri contactLookupUri) { 620a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (hadChanges) { 62136d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded) { 622a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode != SaveMode.JOIN) { 623a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 624a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 625a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else { 626a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 627a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 628a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 629f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 63015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.CLOSE: 6319df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov case SaveMode.HOME: 632f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 63336d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 6343f990ba4e35a99078d831c041290e574a320caa5Walter Jang final Uri lookupUri = maybeConvertToLegacyLookupUri( 6353f990ba4e35a99078d831c041290e574a320caa5Walter Jang mContext, contactLookupUri, mLookupUri); 6363f990ba4e35a99078d831c041290e574a320caa5Walter Jang resultIntent = composeQuickContactsIntent(mContext, lookupUri); 637f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 638f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 639f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 640825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // It is already saved, so prevent that it is saved again 641825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 6425649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan if (mListener != null) mListener.onSaveFinished(resultIntent); 643f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 644a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 64515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.RELOAD: 646dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov case SaveMode.JOIN: 64736d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 648623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann // If it was a JOIN, we are now ready to bring up the join activity. 649e813f5e56ddc6395c5e08e9245e2c5ad41e91724Daniel Lehmann if (saveMode == SaveMode.JOIN && hasValidState()) { 650623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann showJoinAggregateActivity(contactLookupUri); 651623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann } 652623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann 65315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If this was in INSERT, we are changing into an EDIT now. 65415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If it already was an EDIT, we are changing to the new Uri now 65544cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 6561015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov load(Intent.ACTION_EDIT, contactLookupUri, null); 657825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.LOADING; 65815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener); 65915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 66015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann break; 661a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 66215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.SPLIT: 663a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mStatus = Status.CLOSING; 664a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann if (mListener != null) { 6658c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov mListener.onContactSplit(contactLookupUri); 666a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } else { 667a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann Log.d(TAG, "No listener registered, can not call onSplitFinished"); 668a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 669f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 670f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 671f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 672f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 673f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 674f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 675f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 676f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 677f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 678f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 67973a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov if (contactLookupUri == null || !isAdded()) { 680f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 681f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 682f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 683f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 684623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = isContactWritable(); 685c3d202ccbaf93ddd8291672027e59f549c32eee3Brian Attwell final Intent intent = new Intent(UiIntentActions.PICK_JOIN_CONTACT_ACTION); 686c3d202ccbaf93ddd8291672027e59f549c32eee3Brian Attwell intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, mContactIdForJoin); 687a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_JOIN); 688f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 690f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 691f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 692f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 693f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 6942b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin, 695623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann contactId, mContactWritableForJoin, 6962b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED); 6972b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov mContext.startService(intent); 698f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 699f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 700f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 701ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov * Returns true if there is at least one writable raw contact in the current contact. 702ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov */ 703ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov private boolean isContactWritable() { 704a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 705ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov int size = mState.size(); 706ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov for (int i = 0; i < size; i++) { 707851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta entity = mState.get(i); 708851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = entity.getAccountType(accountTypes); 70996e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 710ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return true; 711ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 712ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 713ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return false; 714ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 715ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov 716f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 717f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Returns the contact ID for the currently edited contact or 0 if the contact is new. 718f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 719f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected long getContactId() { 72044cfc56d1701629070384364416c1311b780535dChiao Cheng for (RawContactDelta rawContact : mState) { 72144cfc56d1701629070384364416c1311b780535dChiao Cheng Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID); 72244cfc56d1701629070384364416c1311b780535dChiao Cheng if (contactId != null) { 72344cfc56d1701629070384364416c1311b780535dChiao Cheng return contactId; 724f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 725f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 726f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return 0; 727f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 728f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 729f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 730f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Triggers an asynchronous search for aggregation suggestions. 731f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 7322828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki private void acquireAggregationSuggestions(Context context, 7332828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki RawContactEditorView rawContactEditor) { 7349302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov long rawContactId = rawContactEditor.getRawContactId(); 7359302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (mAggregationSuggestionsRawContactId != rawContactId 7369302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov && mAggregationSuggestionView != null) { 7379302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 7389302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = null; 7399302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionEngine.reset(); 7409302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 7419302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 7429302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = rawContactId; 7439302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 744f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine == null) { 7452828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki mAggregationSuggestionEngine = new AggregationSuggestionEngine(context); 746f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.setListener(this); 747f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.start(); 748f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 749f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 750916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mAggregationSuggestionEngine.setContactId(getContactId()); 751916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 752392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann LabeledEditorView nameEditor = rawContactEditor.getNameEditor(); 753f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.onNameChange(nameEditor.getValues()); 754f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 755f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 756f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 757f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onAggregationSuggestionChange() { 758288532cddfccdc3793dd748d1c75750e2f46cb53Yorke Lee Activity activity = getActivity(); 759288532cddfccdc3793dd748d1c75750e2f46cb53Yorke Lee if ((activity != null && activity.isFinishing()) 76044cfc56d1701629070384364416c1311b780535dChiao Cheng || !isVisible() || mState.isEmpty() || mStatus != Status.EDITING) { 76102cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov return; 76202cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov } 76302cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov 76486625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 765f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 7666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) { 767f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 768f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 769f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 7706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final RawContactEditorView rawContactView = 7716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId); 77202a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki if (rawContactView == null) { 77302a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki return; // Raw contact deleted? 77402a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki } 7756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final View anchorView = rawContactView.findViewById(R.id.anchor_view); 7766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = new ListPopupWindow(mContext, null); 7776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAnchorView(anchorView); 7786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setWidth(anchorView.getWidth()); 7796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 7806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAdapter( 7816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new AggregationSuggestionAdapter(getActivity(), 7826c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mState.size() == 1 && mState.get(0).isContactInsert(), 7836c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa this, mAggregationSuggestionEngine.getSuggestions())); 7846c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setOnItemClickListener(mAggregationSuggestionItemClickListener); 7856c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.show(); 786bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 787bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 788bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 789bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onJoinAction(long contactId, List<Long> rawContactIdList) { 790bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = new long[rawContactIdList.size()]; 791bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov for (int i = 0; i < rawContactIds.length; i++) { 792bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov rawContactIds[i] = rawContactIdList.get(i); 793bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 794bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov JoinSuggestedContactDialogFragment dialog = 795bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new JoinSuggestedContactDialogFragment(); 796bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 797bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putLongArray("rawContactIds", rawContactIds); 798bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 799bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 80074f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov try { 80174f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov dialog.show(getFragmentManager(), "join"); 80274f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } catch (Exception ex) { 80374f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov // No problem - the activity is no longer available to display the dialog 80474f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } 805bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 806bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 807bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class JoinSuggestedContactDialogFragment extends DialogFragment { 808bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 809bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 810bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 811bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 8124292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 813bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_join_dialog_message) 814bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 815bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 816f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 817bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 818bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 819bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 820bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = 821bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getLongArray("rawContactIds"); 822bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doJoinSuggestedContact(rawContactIds); 823bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 824bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 825bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 826bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 827bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 828bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 829bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 830bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 831bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 832bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Joins the suggested contact (specified by the id's of constituent raw 833bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * contacts), save all changes, and stay in the editor. 834bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 835bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doJoinSuggestedContact(long[] rawContactIds) { 836cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 837cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov return; 838cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov } 839cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov 840bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mState.setJoinWithRawContacts(rawContactIds); 8419df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 842bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 843bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 844bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 845bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onEditAction(Uri contactLookupUri) { 846bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov SuggestionEditConfirmationDialogFragment dialog = 847bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new SuggestionEditConfirmationDialogFragment(); 848bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 849bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putParcelable("contactUri", contactLookupUri); 850bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 851bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 852bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.show(getFragmentManager(), "edit"); 853bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 854bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 855bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class SuggestionEditConfirmationDialogFragment extends DialogFragment { 856bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 857bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 858bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 859bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 8604292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 861bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_edit_dialog_message) 862bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 863bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 864f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 865bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 866bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 867bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 868bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Uri contactUri = 869bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getParcelable("contactUri"); 870bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doEditSuggestedContact(contactUri); 871bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 872bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 873bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 874bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 875bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 876bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 877bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 878bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 879bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 880bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Abandons the currently edited contact and switches to editing the suggested 881bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * one, transferring all the data there 882bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 883bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doEditSuggestedContact(Uri contactUri) { 884bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov if (mListener != null) { 885a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann // make sure we don't save this contact when closing down 886a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann mStatus = Status.CLOSING; 887bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mListener.onEditOtherContactRequested( 888bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov contactUri, mState.get(0).getContentValues()); 889bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 890bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 891bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 892a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov public void setAggregationSuggestionViewEnabled(boolean enabled) { 893a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (mAggregationSuggestionView == null) { 894a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov return; 895a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 896a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 897a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 898a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov R.id.aggregation_suggestions); 899a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov int count = itemList.getChildCount(); 900a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov for (int i = 0; i < count; i++) { 901a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov itemList.getChildAt(i).setEnabled(enabled); 902a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 903a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 904a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 905f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 906f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 907cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Joins 908cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 909cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin); 910cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 911daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell outState.putSerializable(KEY_EXPANDED_EDITORS, mExpandedEditors); 912cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 913cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Photos 914cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 915cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelable(KEY_CURRENT_PHOTO_URI, mCurrentPhotoUri); 916cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos); 917cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 918cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Aggregations 919cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putLong(KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID, 920cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mAggregationSuggestionsRawContactId); 921cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 922f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 923f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 924f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 925d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 926f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 927f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (mStatus == Status.SUB_ACTIVITY) { 928f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.EDITING; 929f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov } 930f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 9316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // See if the photo selection handler handles this result. 93291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu if (mCurrentPhotoHandler != null && mCurrentPhotoHandler.handlePhotoActivityResult( 9336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro requestCode, resultCode, data)) { 9346fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return; 9356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 936f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 9376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro switch (requestCode) { 938a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_JOIN: { 9390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Ignore failed requests 9400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) return; 941f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 942f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 943f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 944f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 9454a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann break; 946f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 947ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang default: { 948ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang super.onActivityResult(requestCode, resultCode, data); 949d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell break; 950d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 951f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 952cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 9539cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 954c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann /** 955c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann * Sets the photo stored in mPhoto and writes it to the RawContact with the given id 956c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann */ 957637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee private void setPhoto(long rawContact, Bitmap photo, Uri photoUri) { 958bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact); 959e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 960e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus if (photo == null || photo.getHeight() < 0 || photo.getWidth() < 0) { 961e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus // This is unexpected. 962e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus Log.w(TAG, "Invalid bitmap passed to setPhoto()"); 963e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus } 964e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 9659302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestingEditor != null) { 966c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell requestingEditor.setPhotoEntry(photo); 9677e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell // Immediately set all other photos as non-primary. Otherwise the UI can display 9687e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell // multiple photos as "Primary photo". 9697e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell for (int i = 0; i < mContent.getChildCount(); i++) { 9707e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell final View childView = mContent.getChildAt(i); 9717e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell if (childView instanceof BaseRawContactEditorView 9727e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell && childView != requestingEditor) { 9737e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell final BaseRawContactEditorView rawContactEditor 9747e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell = (BaseRawContactEditorView) childView; 9757e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell rawContactEditor.getPhotoEditor().setSuperPrimary(false); 9767e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } 9777e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } 9789302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } else { 9799302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Log.w(TAG, "The contact that requested the photo is no longer present."); 9809302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 981e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 982637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mUpdatedPhotos.putParcelable(String.valueOf(rawContact), photoUri); 9839302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 9849302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 9859302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov /** 9869302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov * Finds raw contact editor view for the given rawContactId. 9879302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov */ 988bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public BaseRawContactEditorView getRawContactEditorView(long rawContactId) { 989c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 990c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann final View childView = mContent.getChildAt(i); 99172af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 99272af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 9939302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (editor.getRawContactId() == rawContactId) { 9949302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return editor; 995c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 996c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 997c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 9989302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return null; 999c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1000c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1001fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 1002fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann * Returns true if there is currently more than one photo on screen. 1003fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1004fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann private boolean hasMoreThanOnePhoto() { 1005fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int countWithPicture = 0; 100691004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final int numEntities = mState.size(); 100791004b37683c15650eccde68ff04defcf94a1c84Maurice Chu for (int i = 0; i < numEntities; i++) { 1008851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta entity = mState.get(i); 1009851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (entity.isVisible()) { 101091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final ValuesDelta primary = entity.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE); 1011851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (primary != null && primary.getPhoto() != null) { 1012fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann countWithPicture++; 101391004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } else { 1014851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long rawContactId = entity.getRawContactId(); 1015637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee final Uri uri = mUpdatedPhotos.getParcelable(String.valueOf(rawContactId)); 1016637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee if (uri != null) { 1017637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee try { 1018637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mContext.getContentResolver().openInputStream(uri); 101991004b37683c15650eccde68ff04defcf94a1c84Maurice Chu countWithPicture++; 1020637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee } catch (FileNotFoundException e) { 102191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 102291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 102391004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 102491004b37683c15650eccde68ff04defcf94a1c84Maurice Chu 102591004b37683c15650eccde68ff04defcf94a1c84Maurice Chu if (countWithPicture > 1) { 102691004b37683c15650eccde68ff04defcf94a1c84Maurice Chu return true; 1027fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1028fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1029fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1030fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann return false; 10319cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1032222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1033a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann @Override 1034a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann public void onSplitContactConfirmed() { 103544cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 1036b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // This may happen when this Fragment is recreated by the system during users 1037b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // confirming the split action (and thus this method is called just before onCreate()), 1038b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // for example. 1039b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa Log.e(TAG, "mState became null during the user's confirming split action. " + 1040b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa "Cannot perform the save action."); 1041b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa return; 1042b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa } 1043b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa 1044a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann mState.markRawContactsForSplitting(); 10459df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.SPLIT); 1046a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1047a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 10486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 10496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Custom photo handler for the editor. The inner listener that this creates also has a 10506fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * reference to the editor and acts as an {@link EditorListener}, and uses that editor to hold 10516fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * state information in several of the listener methods. 10526fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 10536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoHandler extends PhotoSelectionHandler { 105428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 105528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus final long mRawContactId; 1056e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus private final BaseRawContactEditorView mEditor; 10574bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki private final PhotoActionListener mPhotoEditorListener; 105828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 10596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode, 1060851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state) { 10617e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell super(context, editor.getPhotoEditor().getChangeAnchorView(), photoMode, false, state); 1062e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mEditor = editor; 106328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mRawContactId = editor.getRawContactId(); 10649a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann mPhotoEditorListener = new PhotoEditorListener(); 1065e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1066e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1067e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1068e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus public PhotoActionListener getListener() { 10699a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann return mPhotoEditorListener; 1070e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1071e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1072e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1073637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) { 10744bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 107591004b37683c15650eccde68ff04defcf94a1c84Maurice Chu mCurrentPhotoHandler = this; 1076e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mStatus = Status.SUB_ACTIVITY; 1077637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mCurrentPhotoUri = photoUri; 1078e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus ContactEditorFragment.this.startActivityForResult(intent, requestCode); 10799442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 10809442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 10816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener 10826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro implements EditorListener { 1083fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 10846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 10856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRequest(int request) { 10866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (!hasValidState()) return; 1087a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 10886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (request == EditorListener.REQUEST_PICK_PHOTO) { 10896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro onClick(mEditor.getPhotoEditor()); 10909442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 10917e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell if (request == EditorListener.REQUEST_PICK_PRIMARY_PHOTO) { 10927e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell useAsPrimaryChosen(); 10937e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } 10949442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1095a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 10966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 10976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onDeleteRequested(Editor removedEditor) { 10986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // The picture cannot be deleted, it can only be removed, which is handled by 10996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // onRemovePictureChosen() 11006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1101a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 11026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 11036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to set the selected photo as the (super) primary photo 11046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 11057e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell public void useAsPrimaryChosen() { 11066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set the IsSuperPrimary for each editor 11076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro int count = mContent.getChildCount(); 11086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro for (int i = 0; i < count; i++) { 11096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final View childView = mContent.getChildAt(i); 11106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (childView instanceof BaseRawContactEditorView) { 11116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final BaseRawContactEditorView editor = 11126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro (BaseRawContactEditorView) childView; 11136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final PhotoEditorView photoEditor = editor.getPhotoEditor(); 11146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro photoEditor.setSuperPrimary(editor == mEditor); 11156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 11166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 111791004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 11186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 11199442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 11206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 11216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to remove a picture 11226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 11236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 11246fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRemovePictureChosen() { 1125c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell mEditor.setPhotoEntry(null); 112628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 112728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // Prevent bitmap from being restored if rotate the device. 112828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // (only if we first chose a new photo before removing it) 112928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mUpdatedPhotos.remove(String.valueOf(mRawContactId)); 113091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 11316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 11326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 11336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 1134637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public void onPhotoSelected(Uri uri) throws FileNotFoundException { 1135637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(mContext, uri); 1136637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee setPhoto(mRawContactId, bitmap, uri); 113791004b37683c15650eccde68ff04defcf94a1c84Maurice Chu mCurrentPhotoHandler = null; 113891004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 11396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 11406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 11416fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 1142637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public Uri getCurrentPhotoUri() { 1143637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee return mCurrentPhotoUri; 11446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 11456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 11466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 11476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onPhotoSelectionDismissed() { 11486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Nothing to do. 11499442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 11504a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 11514a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 11522ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1153