ContactEditorFragment.java revision cf718aa47c11453925bb20f7970ca7c897f6e376
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 19f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.accounts.Account; 20cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity; 21bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.AlertDialog; 22bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.Dialog; 23bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.DialogFragment; 24222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager; 25222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 26d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwellimport android.content.ActivityNotFoundException; 27cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 28cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 29e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikovimport android.content.CursorLoader; 30bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface; 31cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 32cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader; 33f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor; 34f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 35d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwellimport android.media.RingtoneManager; 36cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 37cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 389767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock; 39cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 40362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Event; 41362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Organization; 42cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 4391004b37683c15650eccde68ff04defcf94a1c84Maurice Chuimport android.provider.ContactsContract.CommonDataKinds.Photo; 44362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 45be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuanimport android.provider.ContactsContract.Groups; 462013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmannimport android.provider.ContactsContract.Intents; 47f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 48688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Leeimport android.text.TextUtils; 49cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 50cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 51cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu; 52cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater; 53cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem; 54cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 55cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 56d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.AdapterView; 576c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener; 586c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.BaseAdapter; 5980d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 60d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.ListPopupWindow; 61cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast; 62cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 63e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactSaveService; 64e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.GroupMetaDataLoader; 65e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 66e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ContactEditorAccountsChangedActivity; 67e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ContactEditorActivity; 683f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor; 6944cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.AccountTypeManager; 7092101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.Contact; 7192101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.ContactLoader; 7292101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContact; 7392101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContactDelta; 7492101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContactDeltaList; 7592101e77238e450dedb56814cec80edc0adf79c0Walter Jangimport com.android.contacts.common.model.RawContactModifier; 7644cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.ValuesDelta; 7744cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.AccountType; 7844cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.AccountWithDataSet; 7944cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.util.AccountsListAdapter; 8044cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.util.AccountsListAdapter.AccountListFilter; 81e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.PhotoSelectionHandler; 82e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; 83e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.Editor.EditorListener; 84c3d202ccbaf93ddd8291672027e59f549c32eee3Brian Attwellimport com.android.contacts.list.UiIntentActions; 85e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ContactPhotoUtils; 86e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.HelpUtils; 87d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwellimport com.android.contacts.util.PhoneCapabilityTester; 8886625158bdc52855c37e96bf098ba7a213c810d7Chiao Chengimport com.android.contacts.util.UiClosables; 8992101e77238e450dedb56814cec80edc0adf79c0Walter Jang 90851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.google.common.collect.ImmutableList; 9144cfc56d1701629070384364416c1311b780535dChiao Chengimport com.google.common.collect.Lists; 92e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 93637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Leeimport java.io.FileNotFoundException; 94f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections; 95daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwellimport java.util.HashMap; 96f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List; 97f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 983f990ba4e35a99078d831c041290e574a320caa5Walter Jang/** 993f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Contact editor with all fields displayed. 1003f990ba4e35a99078d831c041290e574a320caa5Walter Jang */ 1013f990ba4e35a99078d831c041290e574a320caa5Walter Jangpublic class ContactEditorFragment extends ContactEditorBaseFragment implements 1023f990ba4e35a99078d831c041290e574a320caa5Walter Jang ContactEditor, SplitContactConfirmationDialogFragment.Listener, 103fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener, 1042b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann RawContactReadOnlyEditorView.Listener { 105cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int LOADER_DATA = 1; 107e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private static final int LOADER_GROUPS = 2; 108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 109d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_ACTION = "action"; 110cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_URI = "uri"; 111cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_DISABLE_DELETE_MENU_OPTION = "disableDeleteMenuOption"; 112cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile"; 113cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator"; 115cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 116cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_RAW_CONTACTS = "rawContacts"; 117cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 118cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_EDIT_STATE = "state"; 119ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov private static final String KEY_STATUS = "status"; 120cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 12144cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_HAS_NEW_CONTACT = "hasNewContact"; 12244cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_NEW_CONTACT_READY = "newContactDataReady"; 123cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 124cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_IS_EDIT = "isEdit"; 12544cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady"; 126cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 127cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Phone option menus 128bd127671f7fbcefb87a1b383140dee89cdb7039cBrian Attwell private static final String KEY_SEND_TO_VOICE_MAIL_STATE = "sendToVoicemailState"; 129bd127671f7fbcefb87a1b383140dee89cdb7039cBrian Attwell private static final String KEY_ARE_PHONE_OPTIONS_CHANGEABLE = "arePhoneOptionsChangable"; 130cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CUSTOM_RINGTONE = "customRingtone"; 131cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 132cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Joins 133cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin"; 134cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin"; 135cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 136daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell private static final String KEY_EXPANDED_EDITORS = "expandedEditors"; 137f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 138cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_IS_USER_PROFILE = "isUserProfile"; 139cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 140cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_ENABLED = "enabled"; 141cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 142cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Photos 143cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester"; 144cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_CURRENT_PHOTO_URI = "currentphotouri"; 145cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_UPDATED_PHOTOS = "updatedPhotos"; 146cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 147cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Aggregations 148cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang private static final String KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID = 149cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang "aggregationSuggestionsRawContactId"; 150cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 151a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public static final String SAVE_MODE_EXTRA_KEY = "saveMode"; 152a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 15315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 1547d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * An intent extra that forces the editor to add the edited contact 1557d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * to the default group (e.g. "My Contacts"). 1567d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov */ 1577d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory"; 1587d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 159ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile"; 160ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 161f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos public static final String INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION = 162f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos "disableDeleteMenuOption"; 163f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos 164a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_JOIN = 0; 1656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1; 166d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private static final int REQUEST_CODE_PICK_RINGTONE = 2; 167f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 168fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Context mContext; 169fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Listener mListener; 170e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 171fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private LinearLayout mContent; 172cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 173fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 174fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Parameters passed in on {@link #load} 175fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 176f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mAction; 177b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann private Uri mLookupUri; 178f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Bundle mIntentExtras; 179fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mAutoAddToDefaultGroup; 180fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mDisableDeleteMenuOption = false; 181fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mNewLocalProfile = false; 182cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 183fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 184fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Helpers 185fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 1860353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private ContactEditorUtils mEditorUtils; 187fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private RawContactDeltaComparator mComparator; 188f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 189fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private AggregationSuggestionEngine mAggregationSuggestionEngine; 190cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 191fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 192fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Loaded data 193fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 194fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Used to temporarily store existing contact data during a rebind call (i.e. account switch) 195fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private ImmutableList<RawContact> mRawContacts; 196fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Cursor mGroupMetaData; 1979767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann 198fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 199fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Contact editor state 200fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // 201fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private RawContactDeltaList mState; 202825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private int mStatus; 203825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 20444cfc56d1701629070384364416c1311b780535dChiao Cheng // Whether to show the new contact blank form and if it's corresponding delta is ready. 20544cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mHasNewContact = false; 20644cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mNewContactDataReady = false; 20744cfc56d1701629070384364416c1311b780535dChiao Cheng 20844cfc56d1701629070384364416c1311b780535dChiao Cheng // Whether it's an edit of existing contact and if it's corresponding delta is ready. 20944cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mIsEdit = false; 21044cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mExistingContactDataReady = false; 21144cfc56d1701629070384364416c1311b780535dChiao Cheng 212cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Phone specific option menus 213d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private boolean mSendToVoicemailState; 214d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private boolean mArePhoneOptionsChangable; 215d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private String mCustomRingtone; 216d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 217fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Joins 218fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private long mContactIdForJoin; 219fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mContactWritableForJoin; 220fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 221fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Used to store which raw contact editors have been expanded. Keyed on raw contact ids. 222fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private HashMap<Long, Boolean> mExpandedEditors = new HashMap<Long, Boolean>(); 223fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 224fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mIsUserProfile = false; 225fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 226fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Whether editors and options menu items are enabled 227fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mEnabled = true; 228fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 229fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Whether the name editor should receive focus after being bound 230fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private boolean mRequestFocus; 231fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 23244cfc56d1701629070384364416c1311b780535dChiao Cheng // This is used to pre-populate the editor with a display name when a user edits a read-only 23344cfc56d1701629070384364416c1311b780535dChiao Cheng // contact. 23444cfc56d1701629070384364416c1311b780535dChiao Cheng private String mDefaultDisplayName; 23544cfc56d1701629070384364416c1311b780535dChiao Cheng 236fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Photos 237fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang /** 238fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * The raw contact for which we started "take photo" or "choose photo from gallery" most 239fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * recently. Used to restore {@link #mCurrentPhotoHandler} after orientation change. 240fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang */ 241fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private long mRawContactIdRequestingPhoto; 24244cfc56d1701629070384364416c1311b780535dChiao Cheng 243fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang /** 244fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * The {@link PhotoHandler} for the photo editor for the {@link #mRawContactIdRequestingPhoto} 245fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * raw contact. 246fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * 247fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * A {@link PhotoHandler} is created for each photo editor in {@link #bindPhotoHandler}, but 248fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * the only "active" one should get the activity result. This member represents the active 249fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang * one. 250fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang */ 251fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private PhotoHandler mCurrentPhotoHandler; 252fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Uri mCurrentPhotoUri; 253fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private Bundle mUpdatedPhotos = new Bundle(); 254daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 255fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang // Aggregations 2569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private long mAggregationSuggestionsRawContactId; 2579302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private View mAggregationSuggestionView; 2586c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private ListPopupWindow mAggregationSuggestionPopup; 2596c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2606c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private static final class AggregationSuggestionAdapter extends BaseAdapter { 2616c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final Activity mActivity; 2626c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final boolean mSetNewContact; 2636c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final AggregationSuggestionView.Listener mListener; 2646c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final List<Suggestion> mSuggestions; 2656c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public AggregationSuggestionAdapter(Activity activity, boolean setNewContact, 2676c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) { 2686c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mActivity = activity; 2696c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSetNewContact = setNewContact; 2706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mListener = listener; 2716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSuggestions = suggestions; 2726c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2736c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2746c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 2766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa Suggestion suggestion = (Suggestion) getItem(position); 2776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa LayoutInflater inflater = mActivity.getLayoutInflater(); 2786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView suggestionView = 2796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (AggregationSuggestionView) inflater.inflate( 2806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa R.layout.aggregation_suggestions_item, null); 2816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setNewContact(mSetNewContact); 2826c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setListener(mListener); 2836c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.bindSuggestion(suggestion); 2846c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return suggestionView; 2856c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2866c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2876c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2886c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public long getItemId(int position) { 2896c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return position; 2906c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2916c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2926c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2936c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public Object getItem(int position) { 2946c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.get(position); 2956c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2966c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2976c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2986c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public int getCount() { 2996c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.size(); 3006c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3016c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3026c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 3036c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private OnItemClickListener mAggregationSuggestionItemClickListener = 3046c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new OnItemClickListener() { 3056c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 3066c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 3076c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view; 3086c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.handleItemClickEvent(); 30986625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 3106c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = null; 3116c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3126c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa }; 3136c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 314cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 315cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 316cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 31702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public void setEnabled(boolean enabled) { 31802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mEnabled != enabled) { 31902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = enabled; 32002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mContent != null) { 32102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int count = mContent.getChildCount(); 32202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < count; i++) { 32302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mContent.getChildAt(i).setEnabled(enabled); 32402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 32502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 326a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov setAggregationSuggestionViewEnabled(enabled); 32702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov final Activity activity = getActivity(); 32802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (activity != null) activity.invalidateOptionsMenu(); 32902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 33002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 33102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 332cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 333cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public void onAttach(Activity activity) { 334cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann super.onAttach(activity); 335cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann mContext = activity; 3360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils = ContactEditorUtils.getInstance(mContext); 33792101e77238e450dedb56814cec80edc0adf79c0Walter Jang mComparator = new RawContactDeltaComparator(mContext); 338cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 339cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 340cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 341f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onStop() { 342f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super.onStop(); 34386625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng 34486625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 34586625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng 346825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If anything was left unsaved, save it now but keep the editor open. 347f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) { 348623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann save(SaveMode.RELOAD); 349825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 350f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 351f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 352f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 35336184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee public void onDestroy() { 35436184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee super.onDestroy(); 35536184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee if (mAggregationSuggestionEngine != null) { 35636184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee mAggregationSuggestionEngine.quit(); 35736184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee } 35836184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee } 35936184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee 36036184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee @Override 361cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 362cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 363cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 364f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 365e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 3663648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 367cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 368cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 369cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 370cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 371222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 372222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onActivityCreated(Bundle savedInstanceState) { 373222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann super.onActivityCreated(savedInstanceState); 374222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 375098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng validateAction(mAction); 376098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 37744cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 378098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // The delta list may not have finished loading before orientation change happens. 379098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // In this case, there will be a saved state but deltas will be missing. Reload from 380098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // database. 381825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (Intent.ACTION_EDIT.equals(mAction)) { 382098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // Either... 383098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // 1) orientation change but load never finished. 384098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // or 385098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // 2) not an orientation change. data needs to be loaded for first time. 386825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener); 387098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 388098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } else { 389098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // Orientation change, we already have mState, it was loaded by onCreate 390098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng bindEditors(); 391098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 392098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 39344cfc56d1701629070384364416c1311b780535dChiao Cheng // Handle initial actions only when existing state missing 39444cfc56d1701629070384364416c1311b780535dChiao Cheng if (savedInstanceState == null) { 39544cfc56d1701629070384364416c1311b780535dChiao Cheng if (Intent.ACTION_EDIT.equals(mAction)) { 39644cfc56d1701629070384364416c1311b780535dChiao Cheng mIsEdit = true; 39744cfc56d1701629070384364416c1311b780535dChiao Cheng } else if (Intent.ACTION_INSERT.equals(mAction)) { 39844cfc56d1701629070384364416c1311b780535dChiao Cheng mHasNewContact = true; 3992013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann final Account account = mIntentExtras == null ? null : 4004a1c574cd62eb7ca1e0fcc3a61e5378e5e0787feBrian Attwell (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT); 4012b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = mIntentExtras == null ? null : 4024a1c574cd62eb7ca1e0fcc3a61e5378e5e0787feBrian Attwell mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET); 4032013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann 4042013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann if (account != null) { 4052013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // Account specified in Intent 4062b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro createContact(new AccountWithDataSet(account.name, account.type, dataSet)); 4072013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } else { 4082013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // No Account specified. Let the user choose 40940bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov // Load Accounts async so that we can present them 4100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan selectAccountAndCreateContact(); 4112013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } 412098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 413098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 414098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 415098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 416098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng /** 417098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * Checks if the requested action is valid. 418098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * 419098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * @param action The action to test. 420098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * @throws IllegalArgumentException when the action is invalid. 421098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng */ 422098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng private void validateAction(String action) { 423e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng if (Intent.ACTION_EDIT.equals(action) || Intent.ACTION_INSERT.equals(action) || 424e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(action)) { 425e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng return; 426825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 427098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng throw new IllegalArgumentException("Unknown Action String " + mAction + 428e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT + " or " + 429e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng ContactEditorActivity.ACTION_SAVE_COMPLETED); 430222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 431222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 432e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 433e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onStart() { 434e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener); 435e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov super.onStart(); 436e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 437e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 4383f990ba4e35a99078d831c041290e574a320caa5Walter Jang @Override 4391015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov public void load(String action, Uri lookupUri, Bundle intentExtras) { 440f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mAction = action; 441b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = lookupUri; 442f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mIntentExtras = intentExtras; 4437d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov mAutoAddToDefaultGroup = mIntentExtras != null 444fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY); 445ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = mIntentExtras != null 44636d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro && mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE); 447f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos mDisableDeleteMenuOption = mIntentExtras != null 448f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos && mIntentExtras.getBoolean(INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION); 449f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 450f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 4513f990ba4e35a99078d831c041290e574a320caa5Walter Jang @Override 452f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void setListener(Listener value) { 453f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener = value; 454cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 455cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 456cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 457f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 458d364314c460152db7089b304beec81b3675893baDmitri Plotnikov if (savedState != null) { 459d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // Restore mUri before calling super.onCreate so that onInitializeLoaders 460d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // would already have a uri and an action to work with 461d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mAction = savedState.getString(KEY_ACTION); 462cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mLookupUri = savedState.getParcelable(KEY_URI); 463d364314c460152db7089b304beec81b3675893baDmitri Plotnikov } 464d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 465f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 466f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 467f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (savedState == null) { 468f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If savedState is non-null, onRestoreInstanceState() will restore the generator. 469f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = new ViewIdGenerator(); 470f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 471cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR); 472cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 473cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mDisableDeleteMenuOption = savedState.getBoolean(KEY_DISABLE_DELETE_MENU_OPTION); 474cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE); 475cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 476cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList( 477cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang KEY_RAW_CONTACTS)); 478cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // NOTE: mGroupMetaData is not saved/restored 479cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 480825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Read state from savedState. No loading involved here 481851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE); 482ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov mStatus = savedState.getInt(KEY_STATUS); 483cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 48444cfc56d1701629070384364416c1311b780535dChiao Cheng mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT); 48544cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY); 486cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 487cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mIsEdit = savedState.getBoolean(KEY_IS_EDIT); 48844cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY); 489cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 490cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Phone specific options menus 491bd127671f7fbcefb87a1b383140dee89cdb7039cBrian Attwell mSendToVoicemailState = savedState.getBoolean(KEY_SEND_TO_VOICE_MAIL_STATE); 492cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mArePhoneOptionsChangable = savedState.getBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE); 493bd127671f7fbcefb87a1b383140dee89cdb7039cBrian Attwell mCustomRingtone = savedState.getString(KEY_CUSTOM_RINGTONE); 494cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 495cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Joins 496cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 497cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN); 498cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 499daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell mExpandedEditors = (HashMap<Long, Boolean>) 500daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell savedState.getSerializable(KEY_EXPANDED_EDITORS); 501cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 502cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE); 503cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 504cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mEnabled = savedState.getBoolean(KEY_ENABLED); 505cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 506cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // NOTE: mRequestFocus and mDefaultDisplayName are not saved/restored 507cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 508cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Photos 509cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mRawContactIdRequestingPhoto = savedState.getLong( 510cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 511cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mCurrentPhotoUri = savedState.getParcelable(KEY_CURRENT_PHOTO_URI); 512cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS); 513cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 514cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Aggregations 515cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mAggregationSuggestionsRawContactId = savedState.getLong( 516cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID); 51744cfc56d1701629070384364416c1311b780535dChiao Cheng } 51844cfc56d1701629070384364416c1311b780535dChiao Cheng 51944cfc56d1701629070384364416c1311b780535dChiao Cheng // mState can still be null because it may not have have finished loading before 52044cfc56d1701629070384364416c1311b780535dChiao Cheng // onSaveInstanceState was called. 52144cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState == null) { 52244cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 523cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 524cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 525cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 52644cfc56d1701629070384364416c1311b780535dChiao Cheng public void setData(Contact contact) { 52744cfc56d1701629070384364416c1311b780535dChiao Cheng 528d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann // If we have already loaded data, we do not want to change it here to not confuse the user 52944cfc56d1701629070384364416c1311b780535dChiao Cheng if (!mState.isEmpty()) { 530d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann Log.v(TAG, "Ignoring background change. This will have to be rebased later"); 531d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann return; 532d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann } 533d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann 534fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov // See if this edit operation needs to be redirected to a custom editor 53544cfc56d1701629070384364416c1311b780535dChiao Cheng mRawContacts = contact.getRawContacts(); 53644cfc56d1701629070384364416c1311b780535dChiao Cheng if (mRawContacts.size() == 1) { 53744cfc56d1701629070384364416c1311b780535dChiao Cheng RawContact rawContact = mRawContacts.get(0); 538851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String type = rawContact.getAccountTypeString(); 539851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String dataSet = rawContact.getDataSet(); 54047b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng AccountType accountType = rawContact.getAccountType(mContext); 5412b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (accountType.getEditContactActivityClassName() != null && 5422b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann !accountType.areContactsWritable()) { 543fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 544851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String name = rawContact.getAccountName(); 545851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu long rawContactId = rawContact.getId(); 5462b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mListener.onCustomEditContactActivityRequested( 5472b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro new AccountWithDataSet(name, type, dataSet), 548fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 549fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mIntentExtras, true); 550fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 551fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov return; 552fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 553fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 554fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 555688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee String displayName = null; 55644cfc56d1701629070384364416c1311b780535dChiao Cheng // Check for writable raw contacts. If there are none, then we need to create one so user 55744cfc56d1701629070384364416c1311b780535dChiao Cheng // can edit. For the user profile case, there is already an editable contact. 55844cfc56d1701629070384364416c1311b780535dChiao Cheng if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) { 55944cfc56d1701629070384364416c1311b780535dChiao Cheng mHasNewContact = true; 56044cfc56d1701629070384364416c1311b780535dChiao Cheng 56144cfc56d1701629070384364416c1311b780535dChiao Cheng // This is potentially an asynchronous call and will add deltas to list. 56244cfc56d1701629070384364416c1311b780535dChiao Cheng selectAccountAndCreateContact(); 563688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee displayName = contact.getDisplayName(); 56444cfc56d1701629070384364416c1311b780535dChiao Cheng } 56544cfc56d1701629070384364416c1311b780535dChiao Cheng 56644cfc56d1701629070384364416c1311b780535dChiao Cheng // This also adds deltas to list 567688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee // If displayName is null at this point it is simply ignored later on by the editor. 568688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee bindEditorsForExistingContact(displayName, contact.isUserProfile(), 56944cfc56d1701629070384364416c1311b780535dChiao Cheng mRawContacts); 570d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 571d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell bindMenuItemsForPhone(contact); 572fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 573fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 574fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov @Override 5752b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public void onExternalEditorRequest(AccountWithDataSet account, Uri uri) { 576fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(account, uri, null, false); 577fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 578fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 579daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell @Override 580daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell public void onEditorExpansionChanged() { 581daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell updatedExpandedEditorsMap(); 582daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 583daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 58444cfc56d1701629070384364416c1311b780535dChiao Cheng private void bindEditorsForExistingContact(String displayName, boolean isUserProfile, 58544cfc56d1701629070384364416c1311b780535dChiao Cheng ImmutableList<RawContact> rawContacts) { 58602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov setEnabled(true); 58744cfc56d1701629070384364416c1311b780535dChiao Cheng mDefaultDisplayName = displayName; 58802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 58944cfc56d1701629070384364416c1311b780535dChiao Cheng mState.addAll(rawContacts.iterator()); 5901ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov setIntentExtras(mIntentExtras); 5911ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov mIntentExtras = null; 592e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikov 593ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // For user profile, change the contacts query URI 59444cfc56d1701629070384364416c1311b780535dChiao Cheng mIsUserProfile = isUserProfile; 59548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson boolean localProfileExists = false; 59648ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson 597ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mIsUserProfile) { 598851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContactDelta state : mState) { 59948ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // For profile contacts, we need a different query URI 600ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson state.setProfileQueryUri(); 60148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // Try to find a local profile contact 60248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson if (state.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) { 60348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson localProfileExists = true; 60448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson } 60548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson } 60648ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // Editor should always present a local profile for editing 60748ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson if (!localProfileExists) { 60847b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final RawContact rawContact = new RawContact(); 609851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.setAccountToLocal(); 610851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu 611851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta insert = new RawContactDelta(ValuesDelta.fromAfter( 612851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.getValues())); 61348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson insert.setProfileQueryUri(); 61448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson mState.add(insert); 615ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 616ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 617eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 61844cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = true; 6191ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov bindEditors(); 6201ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 6211ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov 622d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private void bindMenuItemsForPhone(Contact contact) { 623d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mSendToVoicemailState = contact.isSendToVoicemail(); 624d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mCustomRingtone = contact.getCustomRingtone(); 625d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mArePhoneOptionsChangable = arePhoneOptionsChangable(contact); 626d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 627d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 628d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private boolean arePhoneOptionsChangable(Contact contact) { 629d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell return contact != null && !contact.isDirectoryEntry() 630d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell && PhoneCapabilityTester.isPhone(mContext); 631d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 632d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 6331ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov /** 6341ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov * Merges extras from the intent. 6351ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov */ 6361ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov public void setIntentExtras(Bundle extras) { 6371ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov if (extras == null || extras.size() == 0) { 6381ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov return; 639bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 640916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 641a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 642851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContactDelta state : mState) { 643851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = state.getAccountType(accountTypes); 64496e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 6451ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov // Apply extras to the first writable raw contact only 646851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.parseExtras(mContext, type, state, extras); 6471ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov break; 6481ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 6491ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 650f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 651cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 6520353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void selectAccountAndCreateContact() { 6530353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If this is a local profile, then skip the logic about showing the accounts changed 6540353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // activity and create a phone-local contact. 6550353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (mNewLocalProfile) { 6560353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(null); 6570353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 6580353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6590353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 6600353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there is no default account or the accounts have changed such that we need to 6610353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // prompt the user again, then launch the account prompt. 6620353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (mEditorUtils.shouldShowAccountChangedNotification()) { 6630353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class); 6640353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mStatus = Status.SUB_ACTIVITY; 6650353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED); 6660353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } else { 6670353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Otherwise, there should be a default account. Then either create a local contact 6680353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // (if default account is null) or create a contact with the specified account. 6690353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet defaultAccount = mEditorUtils.getDefaultAccount(); 67067e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner createContact(defaultAccount); 6710353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6720353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6730353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 674d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 6750353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan * Create a contact by automatically selecting the first account. If there's no available 6760353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan * account, a device-local contact should be created. 677d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 678d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void createContact() { 6792b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 680a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov AccountTypeManager.getInstance(mContext).getAccounts(true); 6810353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // No Accounts available. Create a phone-local contact. 6820353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (accounts.isEmpty()) { 68340bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(null); 6840353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 685f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 686cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 687d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // We have an account switcher in "create-account" screen, so don't need to ask a user to 688d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // select an account here. 689d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa createContact(accounts.get(0)); 690cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 691cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 692cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 693d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Shows account creation screen associated with a given account. 694d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 695d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param account may be null to signal a device-local contact should be created. 696cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 6972b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void createContact(AccountWithDataSet account) { 698a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 69967e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner final AccountType accountType = accountTypes.getAccountTypeForAccount(account); 700fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 701b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (accountType.getCreateContactActivityClassName() != null) { 702fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 703fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomCreateContactActivityRequested(account, mIntentExtras); 704fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 705fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 706b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov bindEditorsForNewContact(account, accountType); 707fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 708fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 709fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 710d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 711d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Removes a current editor ({@link #mState}) and rebinds new editor for a new account. 712d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Some of old data are reused with new restriction enforced by the new account. 713d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 7142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro * @param oldState Old data being edited. 715d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param oldAccount Old account associated with oldState. 716d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param newAccount New account to be used. 717d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 718d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void rebindEditorsForNewContact( 719851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta oldState, AccountWithDataSet oldAccount, 720851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu AccountWithDataSet newAccount) { 721d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 72267e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner AccountType oldAccountType = accountTypes.getAccountTypeForAccount(oldAccount); 72367e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner AccountType newAccountType = accountTypes.getAccountTypeForAccount(newAccount); 724d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 725d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccountType.getCreateContactActivityClassName() != null) { 726d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa Log.w(TAG, "external activity called in rebind situation"); 727d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (mListener != null) { 728d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras); 729d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 730d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 73144cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = false; 73244cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = false; 73344cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 734d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType); 73544cfc56d1701629070384364416c1311b780535dChiao Cheng if (mIsEdit) { 73644cfc56d1701629070384364416c1311b780535dChiao Cheng bindEditorsForExistingContact(mDefaultDisplayName, mIsUserProfile, mRawContacts); 73744cfc56d1701629070384364416c1311b780535dChiao Cheng } 738d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 739d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 740d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 7412b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet account, 7422b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType accountType) { 743d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(account, accountType, null, null); 744d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 745d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 7462b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet newAccount, 747851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType newAccountType, RawContactDelta oldState, 748851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu AccountType oldAccountType) { 749a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov mStatus = Status.EDITING; 750a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 75147b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final RawContact rawContact = new RawContact(); 75267e83223e954ed54898daa5e32400dbff6d3831aJay Shrauner rawContact.setAccount(newAccount); 753cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 75444cfc56d1701629070384364416c1311b780535dChiao Cheng final ValuesDelta valuesDelta = ValuesDelta.fromAfter(rawContact.getValues()); 75544cfc56d1701629070384364416c1311b780535dChiao Cheng final RawContactDelta insert = new RawContactDelta(valuesDelta); 756d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (oldState == null) { 757d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // Parse any values from incoming intent 758851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras); 759d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 760851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.migrateStateForNewContact(mContext, oldState, insert, 761d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa oldAccountType, newAccountType); 762d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 763f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 76469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov // Ensure we have some default fields (if the account type does not support a field, 765362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmann // ensureKind will not add it, so it is safe to add e.g. Event) 766851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE); 767851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE); 768851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE); 769851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE); 770851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, 771851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu StructuredPostal.CONTENT_ITEM_TYPE); 772f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 773ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // Set the correct URI for saving the contact as a profile 774ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mNewLocalProfile) { 775ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson insert.setProfileQueryUri(); 776ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 777ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 77844cfc56d1701629070384364416c1311b780535dChiao Cheng mState.add(insert); 779f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 780eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 781eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 78244cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = true; 783f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 784cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 785cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 786f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void bindEditors() { 7875671c7e7718c3285dc0391807401083986fcfd51Maurice Chu // bindEditors() can only bind views if there is data in mState, so immediately return 7885671c7e7718c3285dc0391807401083986fcfd51Maurice Chu // if mState is null 78944cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 79044cfc56d1701629070384364416c1311b780535dChiao Cheng return; 79144cfc56d1701629070384364416c1311b780535dChiao Cheng } 79244cfc56d1701629070384364416c1311b780535dChiao Cheng 79344cfc56d1701629070384364416c1311b780535dChiao Cheng // Check if delta list is ready. Delta list is populated from existing data and when 79444cfc56d1701629070384364416c1311b780535dChiao Cheng // editing an read-only contact, it's also populated with newly created data for the 79544cfc56d1701629070384364416c1311b780535dChiao Cheng // blank form. When the data is not ready, skip. This method will be called multiple times. 79644cfc56d1701629070384364416c1311b780535dChiao Cheng if ((mIsEdit && !mExistingContactDataReady) || (mHasNewContact && !mNewContactDataReady)) { 7975671c7e7718c3285dc0391807401083986fcfd51Maurice Chu return; 7985671c7e7718c3285dc0391807401083986fcfd51Maurice Chu } 7995671c7e7718c3285dc0391807401083986fcfd51Maurice Chu 800f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 801f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 802cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 803f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 804f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 805cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 806f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 807f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 808a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 809a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan int numRawContacts = mState.size(); 81044cfc56d1701629070384364416c1311b780535dChiao Cheng 811a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan for (int i = 0; i < numRawContacts; i++) { 812f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 813851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta rawContactDelta = mState.get(i); 814851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (!rawContactDelta.isVisible()) continue; 815f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 816851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = rawContactDelta.getAccountType(accountTypes); 817851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long rawContactId = rawContactDelta.getRawContactId(); 818f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 81972af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor; 8202b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (!type.areContactsWritable()) { 821fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov editor = (BaseRawContactEditorView) inflater.inflate( 8222b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann R.layout.raw_contact_readonly_editor_view, mContent, false); 823fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 824fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view, 825fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mContent, false); 826cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 827daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setListener(this); 828daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(mContext) 829daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell .getAccounts(true); 830daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (mHasNewContact && !mNewLocalProfile && accounts.size() > 1) { 831daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell addAccountSwitcher(mState.get(0), editor); 832d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 833a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan 83402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov editor.setEnabled(mEnabled); 835cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 836daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (mExpandedEditors.containsKey(rawContactId)) { 837daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setCollapsed(mExpandedEditors.get(rawContactId)); 838daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } else { 839daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell // By default, only the first editor will be expanded. 840daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setCollapsed(i != 0); 841daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 842daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 843f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 8447d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 845851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile()); 846daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell editor.setCollapsible(numRawContacts > 1); 847f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 8486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set up the photo handler. 8496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro bindPhotoHandler(editor, type, mState); 8506fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 851c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell // If a new photo was chosen but not yet saved, we need to update the UI to 852c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell // reflect this. 853c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell final Uri photoUri = updatedPhotoUriForRawContact(rawContactId); 854c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell if (photoUri != null) editor.setFullSizedPhoto(photoUri); 85528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 85672af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (editor instanceof RawContactEditorView) { 8572828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki final Activity activity = getActivity(); 85872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final RawContactEditorView rawContactEditor = (RawContactEditorView) editor; 8595ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov EditorListener listener = new EditorListener() { 860f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 861f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 862f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onRequest(int request) { 8632828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki if (activity.isFinishing()) { // Make sure activity is still running. 8642828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki return; 8652828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki } 8662bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) { 8672828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki acquireAggregationSuggestions(activity, rawContactEditor); 868d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell } else if (request == EditorListener.EDITOR_FOCUS_CHANGED) { 869d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell adjustNameFieldsHintDarkness(rawContactEditor); 87011bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 871f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 872f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 873f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 8742293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor removedEditor) { 875f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 8765ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov }; 8775ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov 87844cfc56d1701629070384364416c1311b780535dChiao Cheng final StructuredNameEditorView nameEditor = rawContactEditor.getNameEditor(); 8795ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov if (mRequestFocus) { 8805ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.requestFocus(); 8815ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov mRequestFocus = false; 8825ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov } 8835ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.setEditorListener(listener); 884688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee if (!TextUtils.isEmpty(mDefaultDisplayName)) { 885688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee nameEditor.setDisplayName(mDefaultDisplayName); 886688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee } 887f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 8885ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView phoneticNameEditor = 8895ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov rawContactEditor.getPhoneticNameEditor(); 8905ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov phoneticNameEditor.setEditorListener(listener); 8917d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup); 8927d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 893d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell final TextFieldsEditorView nickNameEditor = 894d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getNickNameEditor(); 895d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell nickNameEditor.setEditorListener(listener); 896d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell 8979302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactId == mAggregationSuggestionsRawContactId) { 8982828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki acquireAggregationSuggestions(activity, rawContactEditor); 899f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 900d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell 901d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell adjustNameFieldsHintDarkness(rawContactEditor); 902f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 903cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 904f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 905eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = false; 906eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 907e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 908e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 909f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 910f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 911a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 912a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann // Refresh Action Bar as the visibility of the join command 913825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Activity can be null if we have been detached from the Activity 914825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann final Activity activity = getActivity(); 915825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (activity != null) activity.invalidateOptionsMenu(); 916daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 917daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell updatedExpandedEditorsMap(); 918daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 919daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell 920daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell /** 921d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell * Adjust how dark the hint text should be on all the names' text fields. 922d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell * 923d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell * @param rawContactEditor editor to update 924d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell */ 925d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell private void adjustNameFieldsHintDarkness(RawContactEditorView rawContactEditor) { 926d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell // Check whether fields contain focus by calling findFocus() instead of hasFocus(). 927d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell // The hasFocus() value is not necessarily up to date. 928d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell final boolean nameFieldsAreNotFocused 929d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell = rawContactEditor.getNameEditor().findFocus() == null 930d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell && rawContactEditor.getPhoneticNameEditor().findFocus() == null 931d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell && rawContactEditor.getNickNameEditor().findFocus() == null; 932d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getNameEditor().setHintColorDark(!nameFieldsAreNotFocused); 933d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getPhoneticNameEditor().setHintColorDark(!nameFieldsAreNotFocused); 934d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell rawContactEditor.getNickNameEditor().setHintColorDark(!nameFieldsAreNotFocused); 935d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell } 936d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell 937d690dff231dd5a81b9bd7563838455f24e49c75cBrian Attwell /** 938daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell * Update the values in {@link #mExpandedEditors}. 939daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell */ 940daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell private void updatedExpandedEditorsMap() { 941daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell for (int i = 0; i < mContent.getChildCount(); i++) { 942daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell final View childView = mContent.getChildAt(i); 943daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (childView instanceof BaseRawContactEditorView) { 944daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell BaseRawContactEditorView childEditor = (BaseRawContactEditorView) childView; 945daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell mExpandedEditors.put(childEditor.getRawContactId(), childEditor.isCollapsed()); 946daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 947daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 9486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 949eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 95028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus /** 951c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell * If we've stashed a temporary file containing a contact's new photo, return its URI. 95228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * @param rawContactId identifies the raw-contact whose Bitmap we'll try to return. 953c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell * @return Uru of photo for specified raw-contact, or null 954c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell */ 955c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell private Uri updatedPhotoUriForRawContact(long rawContactId) { 956c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell return (Uri) mUpdatedPhotos.get(String.valueOf(rawContactId)); 95728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus } 95828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 9596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type, 960851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state) { 9616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final int mode; 9627e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell final boolean showIsPrimaryOption; 9636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (type.areContactsWritable()) { 9646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (editor.hasSetPhoto()) { 9657e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell mode = PhotoActionPopup.Modes.WRITE_ABLE_PHOTO; 9667e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell showIsPrimaryOption = hasMoreThanOnePhoto(); 9676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 968ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.NO_PHOTO; 9697e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell showIsPrimaryOption = false; 9706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 9717e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } else if (editor.hasSetPhoto() && hasMoreThanOnePhoto()) { 9727e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell mode = PhotoActionPopup.Modes.READ_ONLY_PHOTO; 9737e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell showIsPrimaryOption = true; 9746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 9757e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell // Read-only and either no photo or the only photo ==> no options 9767e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell editor.getPhotoEditor().setEditorListener(null); 9777e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell editor.getPhotoEditor().setShowPrimary(false); 9787e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell return; 9796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 98091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final PhotoHandler photoHandler = new PhotoHandler(mContext, editor, mode, state); 9816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro editor.getPhotoEditor().setEditorListener( 98291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu (PhotoHandler.PhotoEditorListener) photoHandler.getListener()); 9837e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell editor.getPhotoEditor().setShowPrimary(showIsPrimaryOption); 9844bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki 9854bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki // Note a newly created raw contact gets some random negative ID, so any value is valid 9864bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki // here. (i.e. don't check against -1 or anything.) 9874bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki if (mRawContactIdRequestingPhoto == editor.getRawContactId()) { 9884bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mCurrentPhotoHandler = photoHandler; 9894bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki } 990cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 991cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 992e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private void bindGroupMetaData() { 993e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov if (mGroupMetaData == null) { 994e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov return; 995e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 996e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 997e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov int editorCount = mContent.getChildCount(); 998e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov for (int i = 0; i < editorCount; i++) { 99972af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann BaseRawContactEditorView editor = (BaseRawContactEditorView) mContent.getChildAt(i); 1000e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov editor.setGroupMetaData(mGroupMetaData); 1001e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1002e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1003e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 10040353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void saveDefaultAccountIfNecessary() { 10050353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Verify that this is a newly created contact, that the contact is composed of only 10060353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // 1 raw contact, and that the contact is not a user profile. 10070353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (!Intent.ACTION_INSERT.equals(mAction) && mState.size() == 1 && 10080353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan !isEditingUserProfile()) { 10090353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 10100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 10110353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 10120353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Find the associated account for this contact (retrieve it here because there are 10130353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // multiple paths to creating a contact and this ensures we always have the correct 10140353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // account). 1015851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta rawContactDelta = mState.get(0); 1016851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String name = rawContactDelta.getAccountName(); 1017851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String type = rawContactDelta.getAccountType(); 1018851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String dataSet = rawContactDelta.getDataSet(); 10190353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 10200353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet account = (name == null || type == null) ? null : 10210353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan new AccountWithDataSet(name, type, dataSet); 10220353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils.saveDefaultAndAllAccounts(account); 10230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 10240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 1025d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void addAccountSwitcher( 1026851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta currentState, BaseRawContactEditorView editor) { 10272b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountWithDataSet currentAccount = new AccountWithDataSet( 1028851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getAccountName(), 1029851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getAccountType(), 1030851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getDataSet()); 1031d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final View accountView = editor.findViewById(R.id.account); 1032daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell final View anchorView = editor.findViewById(R.id.account_selector_container); 1033daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell if (accountView == null) { 1034daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell return; 1035daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell } 1036daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell anchorView.setVisibility(View.VISIBLE); 1037d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa accountView.setOnClickListener(new View.OnClickListener() { 1038d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 1039d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onClick(View v) { 1040d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final ListPopupWindow popup = new ListPopupWindow(mContext, null); 1041a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa final AccountsListAdapter adapter = 10426f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki new AccountsListAdapter(mContext, 10436f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, currentAccount); 1044d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setWidth(anchorView.getWidth()); 1045d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAnchorView(anchorView); 1046d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAdapter(adapter); 1047d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setModal(true); 1048d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 1049d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setOnItemClickListener(new AdapterView.OnItemClickListener() { 1050d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 1051d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, 1052d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa long id) { 105386625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(popup); 10542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountWithDataSet newAccount = adapter.getItem(position); 1055d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (!newAccount.equals(currentAccount)) { 1056d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa rebindEditorsForNewContact(currentState, currentAccount, newAccount); 1057d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 1058d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 1059d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 1060d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.show(); 1061d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 1062d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 1063d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 1064d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 1065b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 1066eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 1067c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan inflater.inflate(R.menu.edit_contact, menu); 1068cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 1069cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1070b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 1071eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onPrepareOptionsMenu(Menu menu) { 10729b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible 10739b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // because the custom action bar contains the "save" button now (not the overflow menu). 10749b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()? 1075692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem doneMenu = menu.findItem(R.id.menu_done); 1076692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem splitMenu = menu.findItem(R.id.menu_split); 1077692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem joinMenu = menu.findItem(R.id.menu_join); 1078692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem helpMenu = menu.findItem(R.id.menu_help); 1079f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee final MenuItem discardMenu = menu.findItem(R.id.menu_discard); 1080d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell final MenuItem sendToVoiceMailMenu = menu.findItem(R.id.menu_send_to_voicemail); 1081d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell final MenuItem ringToneMenu = menu.findItem(R.id.menu_set_ringtone); 1082a513f720d2a15be6a00894c9a2812355d0643fcfBrian Attwell final MenuItem deleteMenu = menu.findItem(R.id.menu_delete); 10835d2e262ab3658118a12fbf6d0edab76484368c24Walter Jang deleteMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 108447b17c83b981172bda672314385eb8920753ba25Brian Attwell deleteMenu.setIcon(R.drawable.ic_delete_white_24dp); 1085692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu 1086692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // Set visibility of menus 1087692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu doneMenu.setVisible(false); 10889b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 1089f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee // Discard menu is only available if at least one raw contact is editable 1090f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee discardMenu.setVisible(mState != null && 1091f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee mState.getFirstWritableRawContact(mContext) != null); 1092f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee 1093692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // help menu depending on whether this is inserting or editing 1094692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu if (Intent.ACTION_INSERT.equals(mAction)) { 1095ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_add); 1096b8671d271e6a7c48aca785b867ef9a86c5012a85Brian Attwell splitMenu.setVisible(false); 1097b8671d271e6a7c48aca785b867ef9a86c5012a85Brian Attwell joinMenu.setVisible(false); 1098a513f720d2a15be6a00894c9a2812355d0643fcfBrian Attwell deleteMenu.setVisible(false); 1099692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } else if (Intent.ACTION_EDIT.equals(mAction)) { 1100ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_edit); 1101b8671d271e6a7c48aca785b867ef9a86c5012a85Brian Attwell // Split only if more than one raw profile and not a user profile 1102b8671d271e6a7c48aca785b867ef9a86c5012a85Brian Attwell splitMenu.setVisible(mState.size() > 1 && !isEditingUserProfile()); 1103b8671d271e6a7c48aca785b867ef9a86c5012a85Brian Attwell // Cannot join a user profile 1104b8671d271e6a7c48aca785b867ef9a86c5012a85Brian Attwell joinMenu.setVisible(!isEditingUserProfile()); 1105f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos deleteMenu.setVisible(!mDisableDeleteMenuOption); 1106692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } else { 1107692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // something else, so don't show the help menu 1108692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu helpMenu.setVisible(false); 1109692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } 111003587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 1111d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Hide telephony-related settings (ringtone, send to voicemail) 1112d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // if we don't have a telephone or are editing a new contact. 1113d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell sendToVoiceMailMenu.setChecked(mSendToVoicemailState); 1114d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell sendToVoiceMailMenu.setVisible(mArePhoneOptionsChangable); 1115d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell ringToneMenu.setVisible(mArePhoneOptionsChangable); 1116d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 111702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int size = menu.size(); 111802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < size; i++) { 111902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov menu.getItem(i).setEnabled(mEnabled); 112002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 1121cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 1122cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1123b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 1124cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public boolean onOptionsItemSelected(MenuItem item) { 1125cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (item.getItemId()) { 11262b24602f1b6661a669762cfc810cc76f51db6e16Brian Attwell case android.R.id.home: 1127f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_done: 11289df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.CLOSE); 1129f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_discard: 1130d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return revert(); 1131a513f720d2a15be6a00894c9a2812355d0643fcfBrian Attwell case R.id.menu_delete: 1132a513f720d2a15be6a00894c9a2812355d0643fcfBrian Attwell if (mListener != null) mListener.onDeleteRequested(mLookupUri); 1133a513f720d2a15be6a00894c9a2812355d0643fcfBrian Attwell return true; 1134f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_split: 1135f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSplitContactAction(); 1136f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_join: 1137f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doJoinContactAction(); 1138d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell case R.id.menu_set_ringtone: 1139d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell doPickRingtone(); 1140d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell return true; 1141d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell case R.id.menu_send_to_voicemail: 1142d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Update state and save 1143d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mSendToVoicemailState = !mSendToVoicemailState; 1144d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell item.setChecked(mSendToVoicemailState); 1145d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell final Intent intent = ContactSaveService.createSetSendToVoicemail( 1146d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mContext, mLookupUri, mSendToVoicemailState); 1147d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mContext.startService(intent); 1148d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell return true; 1149f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1150d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1151f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 1152f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1153cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1154f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSplitContactAction() { 1155f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 1156f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1157a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann final SplitContactConfirmationDialogFragment dialog = 11584a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann new SplitContactConfirmationDialogFragment(); 11594a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.setTargetFragment(this, 0); 11604a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG); 1161f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 1162f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1163f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1164f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doJoinContactAction() { 11654c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov if (!hasValidState()) { 11664c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov return false; 11674c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 11684c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 11694c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // If we just started creating a new contact and haven't added any data, it's too 11704c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // early to do a join 1171764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) { 1172ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus Toast.makeText(mContext, R.string.toast_join_with_empty_contact, 1173a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.LENGTH_LONG).show(); 1174a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov return true; 11754c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 11764c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 11779df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.JOIN); 1178f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1179f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1180f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1181f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Check if our internal {@link #mState} is valid, usually checked before 1182f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * performing user actions. 1183f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1184f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean hasValidState() { 118544cfc56d1701629070384364416c1311b780535dChiao Cheng return mState.size() > 0; 1186f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1187f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1188f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1189764637aba745612a9fdc07adb99c615263916fa8Josh Gargus * Return true if there are any edits to the current contact which need to 1190764637aba745612a9fdc07adb99c615263916fa8Josh Gargus * be saved. 1191764637aba745612a9fdc07adb99c615263916fa8Josh Gargus */ 1192764637aba745612a9fdc07adb99c615263916fa8Josh Gargus private boolean hasPendingChanges() { 1193764637aba745612a9fdc07adb99c615263916fa8Josh Gargus final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1194851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu return RawContactModifier.hasChanges(mState, accountTypes); 1195764637aba745612a9fdc07adb99c615263916fa8Josh Gargus } 1196764637aba745612a9fdc07adb99c615263916fa8Josh Gargus 11973f990ba4e35a99078d831c041290e574a320caa5Walter Jang @Override 11989df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public boolean save(int saveMode) { 1199a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1200f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 1201f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 12038c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov // If we are about to close the editor - there is no need to refresh the data 1204a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.SPLIT) { 12059d2bcfb40d0ee107886eb99eba13a840e944ba43Dianne Hackborn getLoaderManager().destroyLoader(LOADER_DATA); 12068c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov } 12078c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov 1208825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.SAVING; 12096cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 1210764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (!hasPendingChanges()) { 1211ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann if (mLookupUri == null && saveMode == SaveMode.RELOAD) { 1212ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann // We don't have anything to save and there isn't even an existing contact yet. 1213ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann // Nothing to do, simply go back to editing mode 1214ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann mStatus = Status.EDITING; 1215ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann return true; 1216ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann } 121736d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, saveMode, mLookupUri != null, mLookupUri); 12186cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov return true; 12196cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov } 12206cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 1221a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov setEnabled(false); 1222f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 12230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Store account as default account, only if this is a new contact 12240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan saveDefaultAccountIfNecessary(); 12250353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 12260353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Save contact 1227ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState, 1228ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(), 1229ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus ((Activity)mContext).getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED, 1230ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus mUpdatedPhotos); 1231ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus mContext.startService(intent); 123287270e1b58e669354bb1571ced686421c56deb7aJosh Gargus 123387270e1b58e669354bb1571ced686421c56deb7aJosh Gargus // Don't try to save the same photos twice. 123487270e1b58e669354bb1571ced686421c56deb7aJosh Gargus mUpdatedPhotos = new Bundle(); 123587270e1b58e669354bb1571ced686421c56deb7aJosh Gargus 1236f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 1237f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1238f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1239d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private void doPickRingtone() { 1240d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1241d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); 1242d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Allow user to pick 'Default' 1243d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); 1244d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Show only ringtones 1245d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); 1246d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Allow the user to pick a silent ringtone 1247d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); 1248d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1249d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell final Uri ringtoneUri; 1250d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell if (mCustomRingtone != null) { 1251d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell ringtoneUri = Uri.parse(mCustomRingtone); 1252d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } else { 1253d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Otherwise pick default ringtone Uri so that something is selected. 1254d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); 1255d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1256d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1257d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Put checkmark next to the current ringtone for this contact 1258d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri); 1259d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1260d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell // Launch! 1261d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell try { 1262d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE); 1263d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } catch (ActivityNotFoundException ex) { 1264d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell Toast.makeText(mContext, R.string.missing_app, Toast.LENGTH_SHORT).show(); 1265d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1266d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1267d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1268d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell private void handleRingtonePicked(Uri pickedUri) { 1269d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) { 1270d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mCustomRingtone = null; 1271d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } else { 1272d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mCustomRingtone = pickedUri.toString(); 1273d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1274d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell Intent intent = ContactSaveService.createSetRingtone( 1275d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mContext, mLookupUri, mCustomRingtone); 1276d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell mContext.startService(intent); 1277d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1278d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell 1279d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static class CancelEditDialogFragment extends DialogFragment { 1280d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1281d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static void show(ContactEditorFragment fragment) { 1282d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment dialog = new CancelEditDialogFragment(); 1283d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.setTargetFragment(fragment, 0); 1284d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.show(fragment.getFragmentManager(), "cancelEditor"); 1285d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1286d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1287d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 1288d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1289d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov AlertDialog dialog = new AlertDialog.Builder(getActivity()) 12904292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1291d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setMessage(R.string.cancel_confirmation_dialog_message) 12921ba8b6fea4c3f82ded19305874e72a326612aed1Katherine Kuan .setPositiveButton(android.R.string.ok, 1293d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov new DialogInterface.OnClickListener() { 1294d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 1295f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann public void onClick(DialogInterface dialogInterface, int whichButton) { 1296d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ((ContactEditorFragment)getTargetFragment()).doRevertAction(); 1297d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1298d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1299d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ) 1300d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setNegativeButton(android.R.string.cancel, null) 1301d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .create(); 1302d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return dialog; 1303d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1304d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1305d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1306d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private boolean revert() { 130744cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty() || !hasPendingChanges()) { 1308d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov doRevertAction(); 1309d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } else { 1310d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment.show(this); 1311d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1312d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return true; 1313d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1314d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1315d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private void doRevertAction() { 1316825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // When this Fragment is closed we don't want it to auto-save 1317825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 131822fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onReverted(); 1319f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1320f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 13219b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan public void doSaveAction() { 13229b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan save(SaveMode.CLOSE); 13239b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan } 13249b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 13252b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov public void onJoinCompleted(Uri uri) { 132636d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri); 13272b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov } 13282b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov 132936d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, 133036d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro Uri contactLookupUri) { 1331a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (hadChanges) { 133236d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded) { 1333a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode != SaveMode.JOIN) { 1334a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 1335a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1336a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else { 1337a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 1338a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1339a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1340f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 134115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.CLOSE: 13429df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov case SaveMode.HOME: 1343f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 134436d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 13453f990ba4e35a99078d831c041290e574a320caa5Walter Jang final Uri lookupUri = maybeConvertToLegacyLookupUri( 13463f990ba4e35a99078d831c041290e574a320caa5Walter Jang mContext, contactLookupUri, mLookupUri); 13473f990ba4e35a99078d831c041290e574a320caa5Walter Jang resultIntent = composeQuickContactsIntent(mContext, lookupUri); 1348f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1349f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 1350f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1351825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // It is already saved, so prevent that it is saved again 1352825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 13535649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan if (mListener != null) mListener.onSaveFinished(resultIntent); 1354f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1355a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 135615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.RELOAD: 1357dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov case SaveMode.JOIN: 135836d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 1359623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann // If it was a JOIN, we are now ready to bring up the join activity. 1360e813f5e56ddc6395c5e08e9245e2c5ad41e91724Daniel Lehmann if (saveMode == SaveMode.JOIN && hasValidState()) { 1361623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann showJoinAggregateActivity(contactLookupUri); 1362623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann } 1363623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann 136415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If this was in INSERT, we are changing into an EDIT now. 136515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If it already was an EDIT, we are changing to the new Uri now 136644cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 13671015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov load(Intent.ACTION_EDIT, contactLookupUri, null); 1368825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.LOADING; 136915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener); 137015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 137115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann break; 1372a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 137315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.SPLIT: 1374a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mStatus = Status.CLOSING; 1375a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann if (mListener != null) { 13768c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov mListener.onContactSplit(contactLookupUri); 1377a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } else { 1378a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann Log.d(TAG, "No listener registered, can not call onSplitFinished"); 1379a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1380f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1381f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1382f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1383f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1384f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1385f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 1386f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 1387f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 1388f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1389f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 139073a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov if (contactLookupUri == null || !isAdded()) { 1391f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 1392f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1393f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1394f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 1395623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = isContactWritable(); 1396c3d202ccbaf93ddd8291672027e59f549c32eee3Brian Attwell final Intent intent = new Intent(UiIntentActions.PICK_JOIN_CONTACT_ACTION); 1397c3d202ccbaf93ddd8291672027e59f549c32eee3Brian Attwell intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, mContactIdForJoin); 1398a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_JOIN); 1399f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1400f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1401f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1402f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 1403f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1404f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 14052b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin, 1406623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann contactId, mContactWritableForJoin, 14072b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED); 14082b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov mContext.startService(intent); 1409f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1410f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1411f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1412ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov * Returns true if there is at least one writable raw contact in the current contact. 1413ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov */ 1414ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov private boolean isContactWritable() { 1415a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1416ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov int size = mState.size(); 1417ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov for (int i = 0; i < size; i++) { 1418851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta entity = mState.get(i); 1419851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = entity.getAccountType(accountTypes); 142096e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 1421ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return true; 1422ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1423ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1424ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return false; 1425ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1426ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov 14272bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson private boolean isEditingUserProfile() { 14282bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson return mNewLocalProfile || mIsUserProfile; 14292bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson } 14302bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson 1431f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1432f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Returns the contact ID for the currently edited contact or 0 if the contact is new. 1433f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1434f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected long getContactId() { 143544cfc56d1701629070384364416c1311b780535dChiao Cheng for (RawContactDelta rawContact : mState) { 143644cfc56d1701629070384364416c1311b780535dChiao Cheng Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID); 143744cfc56d1701629070384364416c1311b780535dChiao Cheng if (contactId != null) { 143844cfc56d1701629070384364416c1311b780535dChiao Cheng return contactId; 1439f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1440f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1441f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return 0; 1442f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1443f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1444f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1445f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Triggers an asynchronous search for aggregation suggestions. 1446f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 14472828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki private void acquireAggregationSuggestions(Context context, 14482828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki RawContactEditorView rawContactEditor) { 14499302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov long rawContactId = rawContactEditor.getRawContactId(); 14509302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (mAggregationSuggestionsRawContactId != rawContactId 14519302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov && mAggregationSuggestionView != null) { 14529302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 14539302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = null; 14549302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionEngine.reset(); 14559302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 14569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 14579302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = rawContactId; 14589302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 1459f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine == null) { 14602828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki mAggregationSuggestionEngine = new AggregationSuggestionEngine(context); 1461f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.setListener(this); 1462f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.start(); 1463f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1464f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1465916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mAggregationSuggestionEngine.setContactId(getContactId()); 1466916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 1467392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann LabeledEditorView nameEditor = rawContactEditor.getNameEditor(); 1468f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.onNameChange(nameEditor.getValues()); 1469f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1470f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1471f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 1472f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onAggregationSuggestionChange() { 1473288532cddfccdc3793dd748d1c75750e2f46cb53Yorke Lee Activity activity = getActivity(); 1474288532cddfccdc3793dd748d1c75750e2f46cb53Yorke Lee if ((activity != null && activity.isFinishing()) 147544cfc56d1701629070384364416c1311b780535dChiao Cheng || !isVisible() || mState.isEmpty() || mStatus != Status.EDITING) { 147602cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov return; 147702cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov } 147802cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov 147986625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 1480f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 14816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) { 1482f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 1483f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1484f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 14856c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final RawContactEditorView rawContactView = 14866c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId); 148702a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki if (rawContactView == null) { 148802a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki return; // Raw contact deleted? 148902a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki } 14906c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final View anchorView = rawContactView.findViewById(R.id.anchor_view); 14916c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = new ListPopupWindow(mContext, null); 14926c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAnchorView(anchorView); 14936c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setWidth(anchorView.getWidth()); 14946c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 14956c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAdapter( 14966c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new AggregationSuggestionAdapter(getActivity(), 14976c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mState.size() == 1 && mState.get(0).isContactInsert(), 14986c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa this, mAggregationSuggestionEngine.getSuggestions())); 14996c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setOnItemClickListener(mAggregationSuggestionItemClickListener); 15006c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.show(); 1501bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1502bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1503bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1504bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onJoinAction(long contactId, List<Long> rawContactIdList) { 1505bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = new long[rawContactIdList.size()]; 1506bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov for (int i = 0; i < rawContactIds.length; i++) { 1507bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov rawContactIds[i] = rawContactIdList.get(i); 1508bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1509bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov JoinSuggestedContactDialogFragment dialog = 1510bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new JoinSuggestedContactDialogFragment(); 1511bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1512bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putLongArray("rawContactIds", rawContactIds); 1513bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1514bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 151574f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov try { 151674f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov dialog.show(getFragmentManager(), "join"); 151774f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } catch (Exception ex) { 151874f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov // No problem - the activity is no longer available to display the dialog 151974f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } 1520bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1521bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1522bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class JoinSuggestedContactDialogFragment extends DialogFragment { 1523bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1524bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1525bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1526bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 15274292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1528bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_join_dialog_message) 1529bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1530bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1531f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 1532bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1533bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1534bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1535bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = 1536bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getLongArray("rawContactIds"); 1537bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doJoinSuggestedContact(rawContactIds); 1538bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1539bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1540bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1541bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1542bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1543bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1544bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1545bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1546bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1547bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Joins the suggested contact (specified by the id's of constituent raw 1548bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * contacts), save all changes, and stay in the editor. 1549bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1550bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doJoinSuggestedContact(long[] rawContactIds) { 1551cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1552cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov return; 1553cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov } 1554cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov 1555bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mState.setJoinWithRawContacts(rawContactIds); 15569df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 1557bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1558bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1559bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1560bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onEditAction(Uri contactLookupUri) { 1561bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov SuggestionEditConfirmationDialogFragment dialog = 1562bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new SuggestionEditConfirmationDialogFragment(); 1563bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1564bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putParcelable("contactUri", contactLookupUri); 1565bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1566bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 1567bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.show(getFragmentManager(), "edit"); 1568bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1569bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1570bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class SuggestionEditConfirmationDialogFragment extends DialogFragment { 1571bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1572bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1573bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1574bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 15754292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1576bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_edit_dialog_message) 1577bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1578bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1579f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 1580bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1581bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1582bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1583bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Uri contactUri = 1584bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getParcelable("contactUri"); 1585bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doEditSuggestedContact(contactUri); 1586bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1587bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1588bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1589bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1590bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1591bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1592bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1593bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1594bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1595bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Abandons the currently edited contact and switches to editing the suggested 1596bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * one, transferring all the data there 1597bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1598bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doEditSuggestedContact(Uri contactUri) { 1599bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov if (mListener != null) { 1600a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann // make sure we don't save this contact when closing down 1601a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann mStatus = Status.CLOSING; 1602bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mListener.onEditOtherContactRequested( 1603bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov contactUri, mState.get(0).getContentValues()); 1604bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1605bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1606bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1607a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov public void setAggregationSuggestionViewEnabled(boolean enabled) { 1608a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (mAggregationSuggestionView == null) { 1609a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov return; 1610a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1611a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1612a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 1613a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov R.id.aggregation_suggestions); 1614a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov int count = itemList.getChildCount(); 1615a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov for (int i = 0; i < count; i++) { 1616a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov itemList.getChildAt(i).setEnabled(enabled); 1617a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1618a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1619a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1620f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1621f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 1622d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putString(KEY_ACTION, mAction); 1623cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelable(KEY_URI, mLookupUri); 1624cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_DISABLE_DELETE_MENU_OPTION, mDisableDeleteMenuOption); 1625cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile); 1626cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1627cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator); 1628cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1629cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelableArrayList(KEY_RAW_CONTACTS, mRawContacts == null 1630cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang ? Lists.<RawContact>newArrayList() : Lists.newArrayList(mRawContacts)); 1631d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 1632f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (hasValidState()) { 1633f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Store entities with modifications 1634f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_EDIT_STATE, mState); 1635f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1636ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov outState.putInt(KEY_STATUS, mStatus); 1637cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 163844cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact); 163944cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady); 1640cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1641cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_IS_EDIT, mIsEdit); 164244cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady); 1643cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1644cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Phone specific options 1645bd127671f7fbcefb87a1b383140dee89cdb7039cBrian Attwell outState.putBoolean(KEY_SEND_TO_VOICE_MAIL_STATE, mSendToVoicemailState); 1646bd127671f7fbcefb87a1b383140dee89cdb7039cBrian Attwell outState.putBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE, mArePhoneOptionsChangable); 1647cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putString(KEY_CUSTOM_RINGTONE, mCustomRingtone); 1648cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1649cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Joins 1650cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 1651cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin); 1652cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1653daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell outState.putSerializable(KEY_EXPANDED_EDITORS, mExpandedEditors); 165428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 1655cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile); 1656cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1657cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putBoolean(KEY_ENABLED, mEnabled); 1658cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1659cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Photos 1660cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 1661cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelable(KEY_CURRENT_PHOTO_URI, mCurrentPhotoUri); 1662cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos); 1663cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1664cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang // Aggregations 1665cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang outState.putLong(KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID, 1666cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang mAggregationSuggestionsRawContactId); 1667cf718aa47c11453925bb20f7970ca7c897f6e376Walter Jang 1668f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 1669f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1670f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1671d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 1672f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 1673f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (mStatus == Status.SUB_ACTIVITY) { 1674f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.EDITING; 1675f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov } 1676f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 16776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // See if the photo selection handler handles this result. 167891004b37683c15650eccde68ff04defcf94a1c84Maurice Chu if (mCurrentPhotoHandler != null && mCurrentPhotoHandler.handlePhotoActivityResult( 16796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro requestCode, resultCode, data)) { 16806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return; 16816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1682f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 16836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro switch (requestCode) { 1684a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_JOIN: { 16850353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Ignore failed requests 16860353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) return; 1687f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 1688f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 1689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 1690f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 16914a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann break; 1692f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 16930353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan case REQUEST_CODE_ACCOUNTS_CHANGED: { 16940353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Bail if the account selector was not successful. 16950353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) { 16960353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mListener.onReverted(); 16970353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 16980353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 16990353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there's an account specified, use it. 17000353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (data != null) { 17014a1c574cd62eb7ca1e0fcc3a61e5378e5e0787feBrian Attwell AccountWithDataSet account = data.getParcelableExtra( 17024a1c574cd62eb7ca1e0fcc3a61e5378e5e0787feBrian Attwell Intents.Insert.EXTRA_ACCOUNT); 17030353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (account != null) { 17040353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(account); 17050353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 17060353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 17070353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 17080353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there isn't an account specified, then this is likely a phone-local 17090353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // contact, so we should continue setting up the editor by automatically selecting 17100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // the most appropriate account. 17110353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(); 17120353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan break; 17130353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 1714d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell case REQUEST_CODE_PICK_RINGTONE: { 1715d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell if (data != null) { 1716d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell final Uri pickedUri = data.getParcelableExtra( 1717d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell RingtoneManager.EXTRA_RINGTONE_PICKED_URI); 1718d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell handleRingtonePicked(pickedUri); 1719d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1720d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell break; 1721d257a90e1a9a439da44a97d328c3a933d54f2caeBrian Attwell } 1722f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1723cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 17249cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 1725c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann /** 1726c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann * Sets the photo stored in mPhoto and writes it to the RawContact with the given id 1727c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann */ 1728637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee private void setPhoto(long rawContact, Bitmap photo, Uri photoUri) { 1729bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact); 1730e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1731e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus if (photo == null || photo.getHeight() < 0 || photo.getWidth() < 0) { 1732e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus // This is unexpected. 1733e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus Log.w(TAG, "Invalid bitmap passed to setPhoto()"); 1734e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus } 1735e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 17369302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestingEditor != null) { 1737c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell requestingEditor.setPhotoEntry(photo); 17387e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell // Immediately set all other photos as non-primary. Otherwise the UI can display 17397e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell // multiple photos as "Primary photo". 17407e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell for (int i = 0; i < mContent.getChildCount(); i++) { 17417e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell final View childView = mContent.getChildAt(i); 17427e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell if (childView instanceof BaseRawContactEditorView 17437e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell && childView != requestingEditor) { 17447e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell final BaseRawContactEditorView rawContactEditor 17457e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell = (BaseRawContactEditorView) childView; 17467e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell rawContactEditor.getPhotoEditor().setSuperPrimary(false); 17477e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } 17487e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } 17499302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } else { 17509302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Log.w(TAG, "The contact that requested the photo is no longer present."); 17519302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1752e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1753637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mUpdatedPhotos.putParcelable(String.valueOf(rawContact), photoUri); 17549302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 17559302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 17569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov /** 17579302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov * Finds raw contact editor view for the given rawContactId. 17589302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov */ 1759bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public BaseRawContactEditorView getRawContactEditorView(long rawContactId) { 1760c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 1761c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann final View childView = mContent.getChildAt(i); 176272af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 176372af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 17649302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (editor.getRawContactId() == rawContactId) { 17659302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return editor; 1766c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1767c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1768c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 17699302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return null; 1770c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1771c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1772fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 1773fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann * Returns true if there is currently more than one photo on screen. 1774fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1775fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann private boolean hasMoreThanOnePhoto() { 1776fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int countWithPicture = 0; 177791004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final int numEntities = mState.size(); 177891004b37683c15650eccde68ff04defcf94a1c84Maurice Chu for (int i = 0; i < numEntities; i++) { 1779851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta entity = mState.get(i); 1780851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (entity.isVisible()) { 178191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final ValuesDelta primary = entity.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE); 1782851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (primary != null && primary.getPhoto() != null) { 1783fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann countWithPicture++; 178491004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } else { 1785851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long rawContactId = entity.getRawContactId(); 1786637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee final Uri uri = mUpdatedPhotos.getParcelable(String.valueOf(rawContactId)); 1787637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee if (uri != null) { 1788637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee try { 1789637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mContext.getContentResolver().openInputStream(uri); 179091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu countWithPicture++; 1791637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee } catch (FileNotFoundException e) { 179291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 179391004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 179491004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 179591004b37683c15650eccde68ff04defcf94a1c84Maurice Chu 179691004b37683c15650eccde68ff04defcf94a1c84Maurice Chu if (countWithPicture > 1) { 179791004b37683c15650eccde68ff04defcf94a1c84Maurice Chu return true; 1798fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1799fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1800fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1801fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann return false; 18029cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1803222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1804222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann /** 1805222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann * The listener for the data loader 1806222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann */ 1807851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private final LoaderManager.LoaderCallbacks<Contact> mDataLoaderListener = 1808851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 1809fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 1810fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang private long mLoaderStartTime; 1811fb5dc6f857104c38ff49993d7498e8aa5fbc462eWalter Jang 1812222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1813851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 1814222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann mLoaderStartTime = SystemClock.elapsedRealtime(); 181545ee872fe7be69c6b3f0c59167eecd11af467812Makoto Onuki return new ContactLoader(mContext, mLookupUri, true); 1816222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1817222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1818222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1819851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 1820222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long loaderCurrentTime = SystemClock.elapsedRealtime(); 1821222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime)); 18222621c5bb7049401c8bce740005fa60bf1b304b86Makoto Onuki if (!data.isLoaded()) { 1823b4154e46dd98bcb4d85eb6fb210a048c8a7ff7aaBrian Attwell // Item has been deleted. Close activity without saving again. 1824222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.i(TAG, "No contact found. Closing activity"); 1825b4154e46dd98bcb4d85eb6fb210a048c8a7ff7aaBrian Attwell mStatus = Status.CLOSING; 182622fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onContactNotFound(); 1827222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return; 1828222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1829222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1830825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.EDITING; 18316caccaeeed943db323be89853a108f422e670760Dmitri Plotnikov mLookupUri = data.getLookupUri(); 1832222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataStartTime = SystemClock.elapsedRealtime(); 1833222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann setData(data); 1834222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataEndTime = SystemClock.elapsedRealtime(); 1835c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1836222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime)); 1837222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 18384ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1839623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann @Override 1840851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 18414ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1842222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann }; 1843a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 1844e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov /** 1845be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan * The listener for the group meta data loader for all groups. 1846e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov */ 1847e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener = 1848e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov new LoaderCallbacks<Cursor>() { 1849e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1850e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1851e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public CursorLoader onCreateLoader(int id, Bundle args) { 1852be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI); 1853e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1854e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1855e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1856e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1857e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov mGroupMetaData = data; 1858e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 1859e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 18604ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1861f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 18624ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 18634ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1864e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov }; 1865e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1866a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann @Override 1867a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann public void onSplitContactConfirmed() { 186844cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 1869b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // This may happen when this Fragment is recreated by the system during users 1870b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // confirming the split action (and thus this method is called just before onCreate()), 1871b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // for example. 1872b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa Log.e(TAG, "mState became null during the user's confirming split action. " + 1873b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa "Cannot perform the save action."); 1874b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa return; 1875b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa } 1876b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa 1877a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann mState.markRawContactsForSplitting(); 18789df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.SPLIT); 1879a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1880a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 18816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 18826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Custom photo handler for the editor. The inner listener that this creates also has a 18836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * reference to the editor and acts as an {@link EditorListener}, and uses that editor to hold 18846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * state information in several of the listener methods. 18856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 18866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoHandler extends PhotoSelectionHandler { 188728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 188828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus final long mRawContactId; 1889e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus private final BaseRawContactEditorView mEditor; 18904bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki private final PhotoActionListener mPhotoEditorListener; 189128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 18926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode, 1893851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state) { 18947e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell super(context, editor.getPhotoEditor().getChangeAnchorView(), photoMode, false, state); 1895e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mEditor = editor; 189628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mRawContactId = editor.getRawContactId(); 18979a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann mPhotoEditorListener = new PhotoEditorListener(); 1898e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1899e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1900e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1901e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus public PhotoActionListener getListener() { 19029a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann return mPhotoEditorListener; 1903e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1904e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1905e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1906637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) { 19074bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 190891004b37683c15650eccde68ff04defcf94a1c84Maurice Chu mCurrentPhotoHandler = this; 1909e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mStatus = Status.SUB_ACTIVITY; 1910637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mCurrentPhotoUri = photoUri; 1911e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus ContactEditorFragment.this.startActivityForResult(intent, requestCode); 19129442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 19139442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 19146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener 19156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro implements EditorListener { 1916fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 19176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRequest(int request) { 19196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (!hasValidState()) return; 1920a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 19216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (request == EditorListener.REQUEST_PICK_PHOTO) { 19226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro onClick(mEditor.getPhotoEditor()); 19239442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 19247e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell if (request == EditorListener.REQUEST_PICK_PRIMARY_PHOTO) { 19257e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell useAsPrimaryChosen(); 19267e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell } 19279442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1928a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 19296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onDeleteRequested(Editor removedEditor) { 19316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // The picture cannot be deleted, it can only be removed, which is handled by 19326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // onRemovePictureChosen() 19336fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1934a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 19356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 19366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to set the selected photo as the (super) primary photo 19376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 19387e67082d3f7c4ab56945040c0e4617b71c7e5f0bBrian Attwell public void useAsPrimaryChosen() { 19396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set the IsSuperPrimary for each editor 19406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro int count = mContent.getChildCount(); 19416fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro for (int i = 0; i < count; i++) { 19426fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final View childView = mContent.getChildAt(i); 19436fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (childView instanceof BaseRawContactEditorView) { 19446fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final BaseRawContactEditorView editor = 19456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro (BaseRawContactEditorView) childView; 19466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final PhotoEditorView photoEditor = editor.getPhotoEditor(); 19476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro photoEditor.setSuperPrimary(editor == mEditor); 19486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19496fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 195091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 19516fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19529442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 19536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 19546fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to remove a picture 19556fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 19566fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19576fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRemovePictureChosen() { 1958c300521331c04767cd19dfe05ab77567514bbaa0Brian Attwell mEditor.setPhotoEntry(null); 195928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 196028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // Prevent bitmap from being restored if rotate the device. 196128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // (only if we first chose a new photo before removing it) 196228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mUpdatedPhotos.remove(String.valueOf(mRawContactId)); 196391004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 19646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 19666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 1967637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public void onPhotoSelected(Uri uri) throws FileNotFoundException { 1968637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(mContext, uri); 1969637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee setPhoto(mRawContactId, bitmap, uri); 197091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu mCurrentPhotoHandler = null; 197191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 19726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 19746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 1975637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public Uri getCurrentPhotoUri() { 1976637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee return mCurrentPhotoUri; 19776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19786fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 19796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onPhotoSelectionDismissed() { 19816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Nothing to do. 19829442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 19834a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 19844a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 19852ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1986