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.Fragment; 25222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager; 26222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 27cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 28cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentValues; 29cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 30e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikovimport android.content.CursorLoader; 31bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface; 32cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 33cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader; 34f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor; 35f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 3628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargusimport android.graphics.BitmapFactory; 37cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 38cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 399767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock; 40cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 41362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Event; 42362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Organization; 43cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 4491004b37683c15650eccde68ff04defcf94a1c84Maurice Chuimport android.provider.ContactsContract.CommonDataKinds.Photo; 45362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 46f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 47be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuanimport android.provider.ContactsContract.Groups; 482013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmannimport android.provider.ContactsContract.Intents; 49f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 50688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Leeimport android.text.TextUtils; 51cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 52cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 53cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu; 54cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater; 55cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem; 56cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 57cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 58d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.AdapterView; 596c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener; 606c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.BaseAdapter; 6180d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 62d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.ListPopupWindow; 63cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast; 64cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 65e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactSaveService; 66e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.GroupMetaDataLoader; 67e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 68e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ContactEditorAccountsChangedActivity; 69e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.ContactEditorActivity; 70e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.activities.JoinContactActivity; 7144cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.AccountTypeManager; 7244cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.ValuesDelta; 7344cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.AccountType; 7444cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.AccountWithDataSet; 7544cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.model.account.GoogleAccountType; 7644cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.util.AccountsListAdapter; 7744cfc56d1701629070384364416c1311b780535dChiao Chengimport com.android.contacts.common.util.AccountsListAdapter.AccountListFilter; 78e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.PhotoSelectionHandler; 79e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; 80e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.editor.Editor.EditorListener; 81851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.Contact; 82851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.ContactLoader; 83851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContact; 84851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactDelta; 85851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactDeltaList; 86851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactModifier; 87e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ContactPhotoUtils; 88e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.HelpUtils; 8986625158bdc52855c37e96bf098ba7a213c810d7Chiao Chengimport com.android.contacts.util.UiClosables; 90851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.google.common.collect.ImmutableList; 9144cfc56d1701629070384364416c1311b780535dChiao Chengimport com.google.common.collect.Lists; 92e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 93f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.io.File; 94637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Leeimport java.io.FileNotFoundException; 95cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport java.util.ArrayList; 96f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections; 97f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Comparator; 98f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List; 99f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 100a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmannpublic class ContactEditorFragment extends Fragment implements 101d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa SplitContactConfirmationDialogFragment.Listener, 102fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener, 1032b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann RawContactReadOnlyEditorView.Listener { 104cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1052245870a1354df03512010e4968b144840894fb7Frank Sposaro private static final String TAG = ContactEditorFragment.class.getSimpleName(); 106cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int LOADER_DATA = 1; 108e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private static final int LOADER_GROUPS = 2; 109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 110d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_URI = "uri"; 111d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_ACTION = "action"; 112f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_EDIT_STATE = "state"; 1134bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester"; 114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator"; 115637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee private static final String KEY_CURRENT_PHOTO_URI = "currentphotouri"; 116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin"; 117623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin"; 1189302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions"; 11902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private static final String KEY_ENABLED = "enabled"; 120ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov private static final String KEY_STATUS = "status"; 121ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile"; 122ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private static final String KEY_IS_USER_PROFILE = "isUserProfile"; 12328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus private static final String KEY_UPDATED_PHOTOS = "updatedPhotos"; 12444cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_IS_EDIT = "isEdit"; 12544cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_HAS_NEW_CONTACT = "hasNewContact"; 12644cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_NEW_CONTACT_READY = "newContactDataReady"; 12744cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady"; 12844cfc56d1701629070384364416c1311b780535dChiao Cheng private static final String KEY_RAW_CONTACTS = "rawContacts"; 129f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 130a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public static final String SAVE_MODE_EXTRA_KEY = "saveMode"; 131a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 132098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 13315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 1347d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * An intent extra that forces the editor to add the edited contact 1357d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * to the default group (e.g. "My Contacts"). 1367d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov */ 1377d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory"; 1387d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 139ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile"; 140ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 1417d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov /** 14215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Modes that specify what the AsyncTask has to perform after saving 14315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 1449df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public interface SaveMode { 14515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 14615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Close the editor after saving 14715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int CLOSE = 0; 14915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 15015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 15115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Reload the data so that the user can continue editing 15215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 15315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int RELOAD = 1; 15415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 15515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 15615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Split the contact after saving 15715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 15815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int SPLIT = 2; 15915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 16015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 16115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Join another contact after saving 16215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 16315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int JOIN = 3; 1649df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov 1659df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov /** 1669df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov * Navigate to Contacts Home activity after saving. 1679df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov */ 1689df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public static final int HOME = 4; 16915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 170a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 171825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private interface Status { 172825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 173825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * The loader is fetching data 174825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 175825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int LOADING = 0; 176825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 177825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 178825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * Not currently busy. We are waiting for the user to enter data 179825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 180825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int EDITING = 1; 181825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 182825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 183f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * The data is currently being saved. This is used to prevent more 184f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * auto-saves (they shouldn't overlap) 185825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 186825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int SAVING = 2; 187825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 188825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 189a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * Prevents any more saves. This is used if in the following cases: 190a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After Save/Close 191a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After Revert 192a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After the user has accepted an edit suggestion 193825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 194825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int CLOSING = 3; 195f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 196f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov /** 197f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * Prevents saving while running a child activity. 198f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov */ 199f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov public static final int SUB_ACTIVITY = 4; 200825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 201825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 202a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_JOIN = 0; 2036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1; 204f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 2054bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki /** 2064bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * The raw contact for which we started "take photo" or "choose photo from gallery" most 2074bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * recently. Used to restore {@link #mCurrentPhotoHandler} after orientation change. 2084bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki */ 2094bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki private long mRawContactIdRequestingPhoto; 2104bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki /** 2114bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * The {@link PhotoHandler} for the photo editor for the {@link #mRawContactIdRequestingPhoto} 2124bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * raw contact. 2134bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * 2144bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * A {@link PhotoHandler} is created for each photo editor in {@link #bindPhotoHandler}, but 2154bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * the only "active" one should get the activity result. This member represents the active 2164bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki * one. 2174bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki */ 21891004b37683c15650eccde68ff04defcf94a1c84Maurice Chu private PhotoHandler mCurrentPhotoHandler; 219cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 220f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private final EntityDeltaComparator mComparator = new EntityDeltaComparator(); 221f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 222e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private Cursor mGroupMetaData; 223e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 224637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee private Uri mCurrentPhotoUri; 22528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus private Bundle mUpdatedPhotos = new Bundle(); 226cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 227cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Context mContext; 228f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mAction; 229b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann private Uri mLookupUri; 230f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Bundle mIntentExtras; 231cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Listener mListener; 232cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 233f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mContactIdForJoin; 234623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann private boolean mContactWritableForJoin; 235cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 2360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private ContactEditorUtils mEditorUtils; 2370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 238f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private LinearLayout mContent; 239851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private RawContactDeltaList mState; 240cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 241f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 242cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 2439767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann private long mLoaderStartTime; 2449767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann 245825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private int mStatus; 246825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 24744cfc56d1701629070384364416c1311b780535dChiao Cheng // Whether to show the new contact blank form and if it's corresponding delta is ready. 24844cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mHasNewContact = false; 24944cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mNewContactDataReady = false; 25044cfc56d1701629070384364416c1311b780535dChiao Cheng 25144cfc56d1701629070384364416c1311b780535dChiao Cheng // Whether it's an edit of existing contact and if it's corresponding delta is ready. 25244cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mIsEdit = false; 25344cfc56d1701629070384364416c1311b780535dChiao Cheng private boolean mExistingContactDataReady = false; 25444cfc56d1701629070384364416c1311b780535dChiao Cheng 25544cfc56d1701629070384364416c1311b780535dChiao Cheng // This is used to pre-populate the editor with a display name when a user edits a read-only 25644cfc56d1701629070384364416c1311b780535dChiao Cheng // contact. 25744cfc56d1701629070384364416c1311b780535dChiao Cheng private String mDefaultDisplayName; 25844cfc56d1701629070384364416c1311b780535dChiao Cheng 25944cfc56d1701629070384364416c1311b780535dChiao Cheng // Used to temporarily store existing contact data during a rebind call (i.e. account switch) 26044cfc56d1701629070384364416c1311b780535dChiao Cheng private ImmutableList<RawContact> mRawContacts; 26144cfc56d1701629070384364416c1311b780535dChiao Cheng 262f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private AggregationSuggestionEngine mAggregationSuggestionEngine; 2639302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private long mAggregationSuggestionsRawContactId; 2649302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private View mAggregationSuggestionView; 265f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 2666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private ListPopupWindow mAggregationSuggestionPopup; 2676c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2686c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private static final class AggregationSuggestionAdapter extends BaseAdapter { 2696c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final Activity mActivity; 2706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final boolean mSetNewContact; 2716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final AggregationSuggestionView.Listener mListener; 2726c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final List<Suggestion> mSuggestions; 2736c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2746c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public AggregationSuggestionAdapter(Activity activity, boolean setNewContact, 2756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) { 2766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mActivity = activity; 2776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSetNewContact = setNewContact; 2786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mListener = listener; 2796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSuggestions = suggestions; 2806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2826c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2836c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 2846c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa Suggestion suggestion = (Suggestion) getItem(position); 2856c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa LayoutInflater inflater = mActivity.getLayoutInflater(); 2866c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView suggestionView = 2876c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (AggregationSuggestionView) inflater.inflate( 2886c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa R.layout.aggregation_suggestions_item, null); 2896c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setNewContact(mSetNewContact); 2906c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setListener(mListener); 2916c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.bindSuggestion(suggestion); 2926c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return suggestionView; 2936c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2946c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2956c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2966c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public long getItemId(int position) { 2976c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return position; 2986c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2996c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 3006c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 3016c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public Object getItem(int position) { 3026c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.get(position); 3036c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3046c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 3056c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 3066c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public int getCount() { 3076c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.size(); 3086c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3096c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3106c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 3116c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private OnItemClickListener mAggregationSuggestionItemClickListener = 3126c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new OnItemClickListener() { 3136c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 3146c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 3156c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view; 3166c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.handleItemClickEvent(); 31786625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 3186c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = null; 3196c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 3206c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa }; 3216c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 3227d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov private boolean mAutoAddToDefaultGroup; 3237d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 32402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private boolean mEnabled = true; 325eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov private boolean mRequestFocus; 326ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private boolean mNewLocalProfile = false; 327ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private boolean mIsUserProfile = false; 32802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 329cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 330cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 331cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 33202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public void setEnabled(boolean enabled) { 33302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mEnabled != enabled) { 33402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = enabled; 33502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mContent != null) { 33602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int count = mContent.getChildCount(); 33702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < count; i++) { 33802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mContent.getChildAt(i).setEnabled(enabled); 33902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 34002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 341a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov setAggregationSuggestionViewEnabled(enabled); 34202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov final Activity activity = getActivity(); 34302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (activity != null) activity.invalidateOptionsMenu(); 34402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 34502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 34602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 347cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 348cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public void onAttach(Activity activity) { 349cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann super.onAttach(activity); 350cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann mContext = activity; 3510353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils = ContactEditorUtils.getInstance(mContext); 352cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 353cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 354cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 355f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onStop() { 356f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super.onStop(); 35786625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng 35886625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 35986625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng 360825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If anything was left unsaved, save it now but keep the editor open. 361f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) { 362623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann save(SaveMode.RELOAD); 363825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 364f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 365f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 366f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 36736184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee public void onDestroy() { 36836184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee super.onDestroy(); 36936184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee if (mAggregationSuggestionEngine != null) { 37036184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee mAggregationSuggestionEngine.quit(); 37136184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee } 37236184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee } 37336184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee 37436184f630cdb97d0a642de25f69962ef2abfedb1Yorke Lee @Override 375cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 376cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 377cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 378f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 379e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 3803648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 381cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 382cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 383cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 384cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 385222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 386222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onActivityCreated(Bundle savedInstanceState) { 387222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann super.onActivityCreated(savedInstanceState); 388222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 389098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng validateAction(mAction); 390098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 39144cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 392098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // The delta list may not have finished loading before orientation change happens. 393098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // In this case, there will be a saved state but deltas will be missing. Reload from 394098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // database. 395825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (Intent.ACTION_EDIT.equals(mAction)) { 396098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // Either... 397098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // 1) orientation change but load never finished. 398098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // or 399098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // 2) not an orientation change. data needs to be loaded for first time. 400825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener); 401098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 402098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } else { 403098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng // Orientation change, we already have mState, it was loaded by onCreate 404098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng bindEditors(); 405098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 406098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 40744cfc56d1701629070384364416c1311b780535dChiao Cheng // Handle initial actions only when existing state missing 40844cfc56d1701629070384364416c1311b780535dChiao Cheng if (savedInstanceState == null) { 40944cfc56d1701629070384364416c1311b780535dChiao Cheng if (Intent.ACTION_EDIT.equals(mAction)) { 41044cfc56d1701629070384364416c1311b780535dChiao Cheng mIsEdit = true; 41144cfc56d1701629070384364416c1311b780535dChiao Cheng } else if (Intent.ACTION_INSERT.equals(mAction)) { 41244cfc56d1701629070384364416c1311b780535dChiao Cheng mHasNewContact = true; 4132013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann final Account account = mIntentExtras == null ? null : 4142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT); 4152b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = mIntentExtras == null ? null : 4162b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mIntentExtras.getString(Intents.Insert.DATA_SET); 4172013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann 4182013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann if (account != null) { 4192013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // Account specified in Intent 4202b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro createContact(new AccountWithDataSet(account.name, account.type, dataSet)); 4212013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } else { 4222013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // No Account specified. Let the user choose 42340bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov // Load Accounts async so that we can present them 4240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan selectAccountAndCreateContact(); 4252013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } 426098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 427098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 428098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng } 429098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng 430098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng /** 431098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * Checks if the requested action is valid. 432098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * 433098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * @param action The action to test. 434098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng * @throws IllegalArgumentException when the action is invalid. 435098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng */ 436098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng private void validateAction(String action) { 437e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng if (Intent.ACTION_EDIT.equals(action) || Intent.ACTION_INSERT.equals(action) || 438e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(action)) { 439e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng return; 440825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 441098f630c3dd0d993a423425e138f95dba0d7612cChiao Cheng throw new IllegalArgumentException("Unknown Action String " + mAction + 442e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT + " or " + 443e8e94423b463688951f806419dbd73e10e7bf7b4Chiao Cheng ContactEditorActivity.ACTION_SAVE_COMPLETED); 444222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 445222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 446e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 447e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onStart() { 448e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener); 449e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov super.onStart(); 450e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 451e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 4521015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov public void load(String action, Uri lookupUri, Bundle intentExtras) { 453f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mAction = action; 454b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = lookupUri; 455f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mIntentExtras = intentExtras; 4567d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov mAutoAddToDefaultGroup = mIntentExtras != null 4577d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY); 458ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = mIntentExtras != null 45936d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro && mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE); 460f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 461f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 462f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void setListener(Listener value) { 463f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener = value; 464cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 465cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 466cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 467f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 468d364314c460152db7089b304beec81b3675893baDmitri Plotnikov if (savedState != null) { 469d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // Restore mUri before calling super.onCreate so that onInitializeLoaders 470d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // would already have a uri and an action to work with 471b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = savedState.getParcelable(KEY_URI); 472d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mAction = savedState.getString(KEY_ACTION); 473d364314c460152db7089b304beec81b3675893baDmitri Plotnikov } 474d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 475f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 476f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 477f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (savedState == null) { 478f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If savedState is non-null, onRestoreInstanceState() will restore the generator. 479f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = new ViewIdGenerator(); 480f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 481825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Read state from savedState. No loading involved here 482851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE); 4834bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mRawContactIdRequestingPhoto = savedState.getLong( 4844bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 485f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR); 486637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mCurrentPhotoUri = savedState.getParcelable(KEY_CURRENT_PHOTO_URI); 487f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 488623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN); 4899302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = savedState.getLong(KEY_SHOW_JOIN_SUGGESTIONS); 49002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = savedState.getBoolean(KEY_ENABLED); 491ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov mStatus = savedState.getInt(KEY_STATUS); 492ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE); 493ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE); 49428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS); 49544cfc56d1701629070384364416c1311b780535dChiao Cheng mIsEdit = savedState.getBoolean(KEY_IS_EDIT); 49644cfc56d1701629070384364416c1311b780535dChiao Cheng mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT); 49744cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY); 49844cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY); 49944cfc56d1701629070384364416c1311b780535dChiao Cheng mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList( 50044cfc56d1701629070384364416c1311b780535dChiao Cheng KEY_RAW_CONTACTS)); 50144cfc56d1701629070384364416c1311b780535dChiao Cheng 50244cfc56d1701629070384364416c1311b780535dChiao Cheng } 50344cfc56d1701629070384364416c1311b780535dChiao Cheng 50444cfc56d1701629070384364416c1311b780535dChiao Cheng // mState can still be null because it may not have have finished loading before 50544cfc56d1701629070384364416c1311b780535dChiao Cheng // onSaveInstanceState was called. 50644cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState == null) { 50744cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 508cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 509cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 510cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 51144cfc56d1701629070384364416c1311b780535dChiao Cheng public void setData(Contact contact) { 51244cfc56d1701629070384364416c1311b780535dChiao Cheng 513d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann // If we have already loaded data, we do not want to change it here to not confuse the user 51444cfc56d1701629070384364416c1311b780535dChiao Cheng if (!mState.isEmpty()) { 515d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann Log.v(TAG, "Ignoring background change. This will have to be rebased later"); 516d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann return; 517d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann } 518d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann 519fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov // See if this edit operation needs to be redirected to a custom editor 52044cfc56d1701629070384364416c1311b780535dChiao Cheng mRawContacts = contact.getRawContacts(); 52144cfc56d1701629070384364416c1311b780535dChiao Cheng if (mRawContacts.size() == 1) { 52244cfc56d1701629070384364416c1311b780535dChiao Cheng RawContact rawContact = mRawContacts.get(0); 523851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String type = rawContact.getAccountTypeString(); 524851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String dataSet = rawContact.getDataSet(); 52547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng AccountType accountType = rawContact.getAccountType(mContext); 5262b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (accountType.getEditContactActivityClassName() != null && 5272b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann !accountType.areContactsWritable()) { 528fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 529851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String name = rawContact.getAccountName(); 530851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu long rawContactId = rawContact.getId(); 5312b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mListener.onCustomEditContactActivityRequested( 5322b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro new AccountWithDataSet(name, type, dataSet), 533fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 534fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mIntentExtras, true); 535fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 536fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov return; 537fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 538fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 539fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 540688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee String displayName = null; 54144cfc56d1701629070384364416c1311b780535dChiao Cheng // Check for writable raw contacts. If there are none, then we need to create one so user 54244cfc56d1701629070384364416c1311b780535dChiao Cheng // can edit. For the user profile case, there is already an editable contact. 54344cfc56d1701629070384364416c1311b780535dChiao Cheng if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) { 54444cfc56d1701629070384364416c1311b780535dChiao Cheng mHasNewContact = true; 54544cfc56d1701629070384364416c1311b780535dChiao Cheng 54644cfc56d1701629070384364416c1311b780535dChiao Cheng // This is potentially an asynchronous call and will add deltas to list. 54744cfc56d1701629070384364416c1311b780535dChiao Cheng selectAccountAndCreateContact(); 548688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee displayName = contact.getDisplayName(); 54944cfc56d1701629070384364416c1311b780535dChiao Cheng } 55044cfc56d1701629070384364416c1311b780535dChiao Cheng 55144cfc56d1701629070384364416c1311b780535dChiao Cheng // This also adds deltas to list 552688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee // If displayName is null at this point it is simply ignored later on by the editor. 553688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee bindEditorsForExistingContact(displayName, contact.isUserProfile(), 55444cfc56d1701629070384364416c1311b780535dChiao Cheng mRawContacts); 555fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 556fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 557fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov @Override 5582b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public void onExternalEditorRequest(AccountWithDataSet account, Uri uri) { 559fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(account, uri, null, false); 560fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 561fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 56244cfc56d1701629070384364416c1311b780535dChiao Cheng private void bindEditorsForExistingContact(String displayName, boolean isUserProfile, 56344cfc56d1701629070384364416c1311b780535dChiao Cheng ImmutableList<RawContact> rawContacts) { 56402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov setEnabled(true); 56544cfc56d1701629070384364416c1311b780535dChiao Cheng mDefaultDisplayName = displayName; 56602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 56744cfc56d1701629070384364416c1311b780535dChiao Cheng mState.addAll(rawContacts.iterator()); 5681ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov setIntentExtras(mIntentExtras); 5691ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov mIntentExtras = null; 570e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikov 571ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // For user profile, change the contacts query URI 57244cfc56d1701629070384364416c1311b780535dChiao Cheng mIsUserProfile = isUserProfile; 57348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson boolean localProfileExists = false; 57448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson 575ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mIsUserProfile) { 576851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContactDelta state : mState) { 57748ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // For profile contacts, we need a different query URI 578ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson state.setProfileQueryUri(); 57948ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // Try to find a local profile contact 58048ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson if (state.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) { 58148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson localProfileExists = true; 58248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson } 58348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson } 58448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // Editor should always present a local profile for editing 58548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson if (!localProfileExists) { 58647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final RawContact rawContact = new RawContact(); 587851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.setAccountToLocal(); 588851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu 589851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta insert = new RawContactDelta(ValuesDelta.fromAfter( 590851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.getValues())); 59148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson insert.setProfileQueryUri(); 59248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson mState.add(insert); 593ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 594ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 595eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 59644cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = true; 5971ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov bindEditors(); 5981ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 5991ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov 6001ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov /** 6011ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov * Merges extras from the intent. 6021ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov */ 6031ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov public void setIntentExtras(Bundle extras) { 6041ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov if (extras == null || extras.size() == 0) { 6051ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov return; 606bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 607916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 608a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 609851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContactDelta state : mState) { 610851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = state.getAccountType(accountTypes); 61196e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 6121ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov // Apply extras to the first writable raw contact only 613851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.parseExtras(mContext, type, state, extras); 6141ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov break; 6151ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 6161ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 617f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 618cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 6190353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void selectAccountAndCreateContact() { 6200353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If this is a local profile, then skip the logic about showing the accounts changed 6210353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // activity and create a phone-local contact. 6220353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (mNewLocalProfile) { 6230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(null); 6240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 6250353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6260353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 6270353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there is no default account or the accounts have changed such that we need to 6280353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // prompt the user again, then launch the account prompt. 6290353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (mEditorUtils.shouldShowAccountChangedNotification()) { 6300353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class); 6310353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mStatus = Status.SUB_ACTIVITY; 6320353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED); 6330353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } else { 6340353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Otherwise, there should be a default account. Then either create a local contact 6350353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // (if default account is null) or create a contact with the specified account. 6360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet defaultAccount = mEditorUtils.getDefaultAccount(); 6370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (defaultAccount == null) { 6380353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(null); 6390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } else { 6400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(defaultAccount); 6410353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 6440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 645d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 6460353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan * Create a contact by automatically selecting the first account. If there's no available 6470353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan * account, a device-local contact should be created. 648d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 649d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void createContact() { 6502b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 651a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov AccountTypeManager.getInstance(mContext).getAccounts(true); 6520353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // No Accounts available. Create a phone-local contact. 6530353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (accounts.isEmpty()) { 65440bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(null); 6550353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 656f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 657cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 658d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // We have an account switcher in "create-account" screen, so don't need to ask a user to 659d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // select an account here. 660d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa createContact(accounts.get(0)); 661cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 662cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 663cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 664d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Shows account creation screen associated with a given account. 665d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 666d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param account may be null to signal a device-local contact should be created. 667cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 6682b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void createContact(AccountWithDataSet account) { 669a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 670b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType accountType = 6712b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro accountTypes.getAccountType(account != null ? account.type : null, 6722b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro account != null ? account.dataSet : null); 673fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 674b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (accountType.getCreateContactActivityClassName() != null) { 675fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 676fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomCreateContactActivityRequested(account, mIntentExtras); 677fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 678fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 679b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov bindEditorsForNewContact(account, accountType); 680fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 681fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 682fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 683d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 684d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Removes a current editor ({@link #mState}) and rebinds new editor for a new account. 685d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Some of old data are reused with new restriction enforced by the new account. 686d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 6872b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro * @param oldState Old data being edited. 688d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param oldAccount Old account associated with oldState. 689d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param newAccount New account to be used. 690d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 691d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void rebindEditorsForNewContact( 692851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta oldState, AccountWithDataSet oldAccount, 693851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu AccountWithDataSet newAccount) { 694d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 6952b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType oldAccountType = accountTypes.getAccountType( 6962b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro oldAccount.type, oldAccount.dataSet); 6972b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType newAccountType = accountTypes.getAccountType( 6982b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro newAccount.type, newAccount.dataSet); 699d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 700d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccountType.getCreateContactActivityClassName() != null) { 701d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa Log.w(TAG, "external activity called in rebind situation"); 702d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (mListener != null) { 703d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras); 704d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 705d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 70644cfc56d1701629070384364416c1311b780535dChiao Cheng mExistingContactDataReady = false; 70744cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = false; 70844cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 709d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType); 71044cfc56d1701629070384364416c1311b780535dChiao Cheng if (mIsEdit) { 71144cfc56d1701629070384364416c1311b780535dChiao Cheng bindEditorsForExistingContact(mDefaultDisplayName, mIsUserProfile, mRawContacts); 71244cfc56d1701629070384364416c1311b780535dChiao Cheng } 713d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 714d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 715d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 7162b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet account, 7172b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType accountType) { 718d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(account, accountType, null, null); 719d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 720d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 7212b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet newAccount, 722851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType newAccountType, RawContactDelta oldState, 723851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu AccountType oldAccountType) { 724a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov mStatus = Status.EDITING; 725a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 72647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final RawContact rawContact = new RawContact(); 727d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccount != null) { 728851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.setAccount(newAccount); 729f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 730851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.setAccountToLocal(); 731cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 732cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 73344cfc56d1701629070384364416c1311b780535dChiao Cheng final ValuesDelta valuesDelta = ValuesDelta.fromAfter(rawContact.getValues()); 73444cfc56d1701629070384364416c1311b780535dChiao Cheng final RawContactDelta insert = new RawContactDelta(valuesDelta); 735d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (oldState == null) { 736d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // Parse any values from incoming intent 737851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras); 738d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 739851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.migrateStateForNewContact(mContext, oldState, insert, 740d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa oldAccountType, newAccountType); 741d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 742f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 74369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov // Ensure we have some default fields (if the account type does not support a field, 744362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmann // ensureKind will not add it, so it is safe to add e.g. Event) 745851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE); 746851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE); 747851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE); 748851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE); 749851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.ensureKindExists(insert, newAccountType, 750851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu StructuredPostal.CONTENT_ITEM_TYPE); 751f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 752ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // Set the correct URI for saving the contact as a profile 753ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mNewLocalProfile) { 754ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson insert.setProfileQueryUri(); 755ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 756ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 75744cfc56d1701629070384364416c1311b780535dChiao Cheng mState.add(insert); 758f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 759eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 760eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 76144cfc56d1701629070384364416c1311b780535dChiao Cheng mNewContactDataReady = true; 762f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 763cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 764cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 765f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void bindEditors() { 7665671c7e7718c3285dc0391807401083986fcfd51Maurice Chu // bindEditors() can only bind views if there is data in mState, so immediately return 7675671c7e7718c3285dc0391807401083986fcfd51Maurice Chu // if mState is null 76844cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 76944cfc56d1701629070384364416c1311b780535dChiao Cheng return; 77044cfc56d1701629070384364416c1311b780535dChiao Cheng } 77144cfc56d1701629070384364416c1311b780535dChiao Cheng 77244cfc56d1701629070384364416c1311b780535dChiao Cheng // Check if delta list is ready. Delta list is populated from existing data and when 77344cfc56d1701629070384364416c1311b780535dChiao Cheng // editing an read-only contact, it's also populated with newly created data for the 77444cfc56d1701629070384364416c1311b780535dChiao Cheng // blank form. When the data is not ready, skip. This method will be called multiple times. 77544cfc56d1701629070384364416c1311b780535dChiao Cheng if ((mIsEdit && !mExistingContactDataReady) || (mHasNewContact && !mNewContactDataReady)) { 7765671c7e7718c3285dc0391807401083986fcfd51Maurice Chu return; 7775671c7e7718c3285dc0391807401083986fcfd51Maurice Chu } 7785671c7e7718c3285dc0391807401083986fcfd51Maurice Chu 779f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 780f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 781cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 782f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 783f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 784cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 785f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 786f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 787a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 788a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan int numRawContacts = mState.size(); 78944cfc56d1701629070384364416c1311b780535dChiao Cheng 790a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan for (int i = 0; i < numRawContacts; i++) { 791f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 792851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta rawContactDelta = mState.get(i); 793851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (!rawContactDelta.isVisible()) continue; 794f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 795851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = rawContactDelta.getAccountType(accountTypes); 796851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long rawContactId = rawContactDelta.getRawContactId(); 797f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 79872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor; 7992b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (!type.areContactsWritable()) { 800fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov editor = (BaseRawContactEditorView) inflater.inflate( 8012b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann R.layout.raw_contact_readonly_editor_view, mContent, false); 8022b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann ((RawContactReadOnlyEditorView) editor).setListener(this); 803fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 804fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view, 805fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mContent, false); 806cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 80744cfc56d1701629070384364416c1311b780535dChiao Cheng if (mHasNewContact && !mNewLocalProfile) { 8082b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 809d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager.getInstance(mContext).getAccounts(true); 81044cfc56d1701629070384364416c1311b780535dChiao Cheng if (accounts.size() > 1) { 811d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa addAccountSwitcher(mState.get(0), editor); 812a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan } else { 813a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan disableAccountSwitcher(editor); 814d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 815a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan } else { 816a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan disableAccountSwitcher(editor); 817d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 818a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan 81902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov editor.setEnabled(mEnabled); 820cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 821f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 8227d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 823851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile()); 824f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 8256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set up the photo handler. 8266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro bindPhotoHandler(editor, type, mState); 8276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 82828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // If a new photo was chosen but not yet saved, we need to 82928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // update the thumbnail to reflect this. 83028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus Bitmap bitmap = updatedBitmapForRawContact(rawContactId); 83128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus if (bitmap != null) editor.setPhotoBitmap(bitmap); 83228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 83372af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (editor instanceof RawContactEditorView) { 8342828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki final Activity activity = getActivity(); 83572af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final RawContactEditorView rawContactEditor = (RawContactEditorView) editor; 8365ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov EditorListener listener = new EditorListener() { 837f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 838f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 839f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onRequest(int request) { 8402828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki if (activity.isFinishing()) { // Make sure activity is still running. 8412828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki return; 8422828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki } 8432bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) { 8442828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki acquireAggregationSuggestions(activity, rawContactEditor); 84511bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 846f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 847f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 848f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 8492293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor removedEditor) { 850f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 8515ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov }; 8525ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov 85344cfc56d1701629070384364416c1311b780535dChiao Cheng final StructuredNameEditorView nameEditor = rawContactEditor.getNameEditor(); 8545ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov if (mRequestFocus) { 8555ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.requestFocus(); 8565ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov mRequestFocus = false; 8575ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov } 8585ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.setEditorListener(listener); 859688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee if (!TextUtils.isEmpty(mDefaultDisplayName)) { 860688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee nameEditor.setDisplayName(mDefaultDisplayName); 861688c228b2d7cf0c812fb673451f24e7cb457d63bYorke Lee } 862f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 8635ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView phoneticNameEditor = 8645ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov rawContactEditor.getPhoneticNameEditor(); 8655ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov phoneticNameEditor.setEditorListener(listener); 8667d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup); 8677d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 8689302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactId == mAggregationSuggestionsRawContactId) { 8692828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki acquireAggregationSuggestions(activity, rawContactEditor); 870f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 871f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 872cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 873f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 874eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = false; 875eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 876e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 877e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 878f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 879f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 880a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 881a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann // Refresh Action Bar as the visibility of the join command 882825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Activity can be null if we have been detached from the Activity 883825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann final Activity activity = getActivity(); 884825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (activity != null) activity.invalidateOptionsMenu(); 8856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 886eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 88728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus /** 88828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * If we've stashed a temporary file containing a contact's new photo, 88928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * decode it and return the bitmap. 89028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * @param rawContactId identifies the raw-contact whose Bitmap we'll try to return. 89128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * @return Bitmap of photo for specified raw-contact, or null 89228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus */ 89328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus private Bitmap updatedBitmapForRawContact(long rawContactId) { 89428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus String path = mUpdatedPhotos.getString(String.valueOf(rawContactId)); 89528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus return BitmapFactory.decodeFile(path); 89628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus } 89728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 8986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type, 899851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state) { 9006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final int mode; 9016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (type.areContactsWritable()) { 9026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (editor.hasSetPhoto()) { 9036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (hasMoreThanOnePhoto()) { 904ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.PHOTO_ALLOW_PRIMARY; 9056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 906ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.PHOTO_DISALLOW_PRIMARY; 9076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 9086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 909ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.NO_PHOTO; 9106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 9116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 9126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (editor.hasSetPhoto() && hasMoreThanOnePhoto()) { 913ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.READ_ONLY_ALLOW_PRIMARY; 9146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 9156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Read-only and either no photo or the only photo ==> no options 916740552201d103b80bc49ea8a39a30536222672eaDaniel Lehmann editor.getPhotoEditor().setEditorListener(null); 9176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return; 9186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 9196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 92091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final PhotoHandler photoHandler = new PhotoHandler(mContext, editor, mode, state); 9216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro editor.getPhotoEditor().setEditorListener( 92291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu (PhotoHandler.PhotoEditorListener) photoHandler.getListener()); 9234bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki 9244bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki // Note a newly created raw contact gets some random negative ID, so any value is valid 9254bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki // here. (i.e. don't check against -1 or anything.) 9264bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki if (mRawContactIdRequestingPhoto == editor.getRawContactId()) { 9274bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mCurrentPhotoHandler = photoHandler; 9284bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki } 929cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 930cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 931e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private void bindGroupMetaData() { 932e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov if (mGroupMetaData == null) { 933e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov return; 934e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 935e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 936e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov int editorCount = mContent.getChildCount(); 937e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov for (int i = 0; i < editorCount; i++) { 93872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann BaseRawContactEditorView editor = (BaseRawContactEditorView) mContent.getChildAt(i); 939e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov editor.setGroupMetaData(mGroupMetaData); 940e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 941e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 942e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 9430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void saveDefaultAccountIfNecessary() { 9440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Verify that this is a newly created contact, that the contact is composed of only 9450353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // 1 raw contact, and that the contact is not a user profile. 9460353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (!Intent.ACTION_INSERT.equals(mAction) && mState.size() == 1 && 9470353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan !isEditingUserProfile()) { 9480353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 9490353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 9500353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 9510353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Find the associated account for this contact (retrieve it here because there are 9520353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // multiple paths to creating a contact and this ensures we always have the correct 9530353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // account). 954851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta rawContactDelta = mState.get(0); 955851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String name = rawContactDelta.getAccountName(); 956851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String type = rawContactDelta.getAccountType(); 957851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String dataSet = rawContactDelta.getDataSet(); 9580353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 9590353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet account = (name == null || type == null) ? null : 9600353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan new AccountWithDataSet(name, type, dataSet); 9610353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils.saveDefaultAndAllAccounts(account); 9620353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 9630353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 964d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void addAccountSwitcher( 965851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta currentState, BaseRawContactEditorView editor) { 9662b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountWithDataSet currentAccount = new AccountWithDataSet( 967851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getAccountName(), 968851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getAccountType(), 969851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu currentState.getDataSet()); 970d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final View accountView = editor.findViewById(R.id.account); 971fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan final View anchorView = editor.findViewById(R.id.account_container); 972d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa accountView.setOnClickListener(new View.OnClickListener() { 973d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 974d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onClick(View v) { 975d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final ListPopupWindow popup = new ListPopupWindow(mContext, null); 976a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa final AccountsListAdapter adapter = 9776f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki new AccountsListAdapter(mContext, 9786f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, currentAccount); 979d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setWidth(anchorView.getWidth()); 980d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAnchorView(anchorView); 981d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAdapter(adapter); 982d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setModal(true); 983d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 984d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setOnItemClickListener(new AdapterView.OnItemClickListener() { 985d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 986d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, 987d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa long id) { 98886625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(popup); 9892b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountWithDataSet newAccount = adapter.getItem(position); 990d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (!newAccount.equals(currentAccount)) { 991d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa rebindEditorsForNewContact(currentState, currentAccount, newAccount); 992d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 993d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 994d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 995d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.show(); 996d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 997d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 998d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 999d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 1000a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan private void disableAccountSwitcher(BaseRawContactEditorView editor) { 1001a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan // Remove the pressed state from the account header because the user cannot switch accounts 1002a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan // on an existing contact 1003a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan final View accountView = editor.findViewById(R.id.account); 1004740552201d103b80bc49ea8a39a30536222672eaDaniel Lehmann accountView.setBackground(null); 1005a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan accountView.setEnabled(false); 1006a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan } 1007a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan 1008b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 1009eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 1010c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan inflater.inflate(R.menu.edit_contact, menu); 1011cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 1012cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1013b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 1014eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onPrepareOptionsMenu(Menu menu) { 10159b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible 10169b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // because the custom action bar contains the "save" button now (not the overflow menu). 10179b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()? 1018692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem doneMenu = menu.findItem(R.id.menu_done); 1019692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem splitMenu = menu.findItem(R.id.menu_split); 1020692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem joinMenu = menu.findItem(R.id.menu_join); 1021692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem helpMenu = menu.findItem(R.id.menu_help); 1022f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee final MenuItem discardMenu = menu.findItem(R.id.menu_discard); 1023692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu 1024692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // Set visibility of menus 1025692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu doneMenu.setVisible(false); 10269b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 102703587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson // Split only if more than one raw profile and not a user profile 102844cfc56d1701629070384364416c1311b780535dChiao Cheng splitMenu.setVisible(mState.size() > 1 && !isEditingUserProfile()); 102903587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 1030692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // Cannot join a user profile 1031692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu joinMenu.setVisible(!isEditingUserProfile()); 1032692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu 1033f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee // Discard menu is only available if at least one raw contact is editable 1034f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee discardMenu.setVisible(mState != null && 1035f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee mState.getFirstWritableRawContact(mContext) != null); 1036f3c73113f0882d79aece54bc8ad467a5d0660f62Yorke Lee 1037692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // help menu depending on whether this is inserting or editing 1038692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu if (Intent.ACTION_INSERT.equals(mAction)) { 1039692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // inserting 1040ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_add); 1041692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } else if (Intent.ACTION_EDIT.equals(mAction)) { 1042692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // editing 1043ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_edit); 1044692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } else { 1045692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // something else, so don't show the help menu 1046692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu helpMenu.setVisible(false); 1047692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } 104803587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 104902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int size = menu.size(); 105002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < size; i++) { 105102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov menu.getItem(i).setEnabled(mEnabled); 105202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 1053cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 1054cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1055b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 1056cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public boolean onOptionsItemSelected(MenuItem item) { 1057cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (item.getItemId()) { 1058f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_done: 10599df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.CLOSE); 1060f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_discard: 1061d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return revert(); 1062f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_split: 1063f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSplitContactAction(); 1064f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_join: 1065f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doJoinContactAction(); 1066f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1067f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 1068f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1069cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1070f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSplitContactAction() { 1071f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 1072f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1073a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann final SplitContactConfirmationDialogFragment dialog = 10744a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann new SplitContactConfirmationDialogFragment(); 10754a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.setTargetFragment(this, 0); 10764a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG); 1077f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 1078f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1079f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1080f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doJoinContactAction() { 10814c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov if (!hasValidState()) { 10824c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov return false; 10834c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 10844c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 10854c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // If we just started creating a new contact and haven't added any data, it's too 10864c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // early to do a join 1087764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) { 1088ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus Toast.makeText(mContext, R.string.toast_join_with_empty_contact, 1089a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.LENGTH_LONG).show(); 1090a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov return true; 10914c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 10924c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 10939df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.JOIN); 1094f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1095f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1096f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1097f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Check if our internal {@link #mState} is valid, usually checked before 1098f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * performing user actions. 1099f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1100f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean hasValidState() { 110144cfc56d1701629070384364416c1311b780535dChiao Cheng return mState.size() > 0; 1102f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1103f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1105764637aba745612a9fdc07adb99c615263916fa8Josh Gargus * Return true if there are any edits to the current contact which need to 1106764637aba745612a9fdc07adb99c615263916fa8Josh Gargus * be saved. 1107764637aba745612a9fdc07adb99c615263916fa8Josh Gargus */ 1108764637aba745612a9fdc07adb99c615263916fa8Josh Gargus private boolean hasPendingChanges() { 1109764637aba745612a9fdc07adb99c615263916fa8Josh Gargus final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1110851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu return RawContactModifier.hasChanges(mState, accountTypes); 1111764637aba745612a9fdc07adb99c615263916fa8Josh Gargus } 1112764637aba745612a9fdc07adb99c615263916fa8Josh Gargus 1113764637aba745612a9fdc07adb99c615263916fa8Josh Gargus /** 1114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Saves or creates the contact based on the mode, and if successful 1115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * finishes the activity. 1116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 11179df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public boolean save(int saveMode) { 1118a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1119f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 1120f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1121f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 11228c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov // If we are about to close the editor - there is no need to refresh the data 1123a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.SPLIT) { 11249d2bcfb40d0ee107886eb99eba13a840e944ba43Dianne Hackborn getLoaderManager().destroyLoader(LOADER_DATA); 11258c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov } 11268c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov 1127825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.SAVING; 11286cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 1129764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (!hasPendingChanges()) { 1130ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann if (mLookupUri == null && saveMode == SaveMode.RELOAD) { 1131ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann // We don't have anything to save and there isn't even an existing contact yet. 1132ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann // Nothing to do, simply go back to editing mode 1133ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann mStatus = Status.EDITING; 1134ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann return true; 1135ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann } 113636d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, saveMode, mLookupUri != null, mLookupUri); 11376cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov return true; 11386cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov } 11396cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 1140a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov setEnabled(false); 1141f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 11420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Store account as default account, only if this is a new contact 11430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan saveDefaultAccountIfNecessary(); 11440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 11450353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Save contact 1146ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState, 1147ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(), 1148ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus ((Activity)mContext).getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED, 1149ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus mUpdatedPhotos); 1150ebc17929007ecf12f25b8e90023766e8a083d11eJosh Gargus mContext.startService(intent); 115187270e1b58e669354bb1571ced686421c56deb7aJosh Gargus 115287270e1b58e669354bb1571ced686421c56deb7aJosh Gargus // Don't try to save the same photos twice. 115387270e1b58e669354bb1571ced686421c56deb7aJosh Gargus mUpdatedPhotos = new Bundle(); 115487270e1b58e669354bb1571ced686421c56deb7aJosh Gargus 1155f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 1156f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1157f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1158d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static class CancelEditDialogFragment extends DialogFragment { 1159d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1160d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static void show(ContactEditorFragment fragment) { 1161d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment dialog = new CancelEditDialogFragment(); 1162d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.setTargetFragment(fragment, 0); 1163d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.show(fragment.getFragmentManager(), "cancelEditor"); 1164d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1165d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1166d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 1167d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1168d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov AlertDialog dialog = new AlertDialog.Builder(getActivity()) 11694292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1170d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setMessage(R.string.cancel_confirmation_dialog_message) 11711ba8b6fea4c3f82ded19305874e72a326612aed1Katherine Kuan .setPositiveButton(android.R.string.ok, 1172d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov new DialogInterface.OnClickListener() { 1173d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 1174f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann public void onClick(DialogInterface dialogInterface, int whichButton) { 1175d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ((ContactEditorFragment)getTargetFragment()).doRevertAction(); 1176d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1177d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1178d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ) 1179d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setNegativeButton(android.R.string.cancel, null) 1180d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .create(); 1181d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return dialog; 1182d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1183d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1184d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1185d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private boolean revert() { 118644cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty() || !hasPendingChanges()) { 1187d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov doRevertAction(); 1188d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } else { 1189d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment.show(this); 1190d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1191d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return true; 1192d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1193d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1194d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private void doRevertAction() { 1195825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // When this Fragment is closed we don't want it to auto-save 1196825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 119722fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onReverted(); 1198f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1199f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 12009b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan public void doSaveAction() { 12019b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan save(SaveMode.CLOSE); 12029b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan } 12039b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 12042b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov public void onJoinCompleted(Uri uri) { 120536d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri); 12062b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov } 12072b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov 120836d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, 120936d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro Uri contactLookupUri) { 1210a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (hadChanges) { 121136d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded) { 1212a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode != SaveMode.JOIN) { 1213a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 1214a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1215a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else { 1216a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 1217a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1218a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1219f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 122015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.CLOSE: 12219df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov case SaveMode.HOME: 1222f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 122336d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 1224b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann final String requestAuthority = 1225b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri == null ? null : mLookupUri.getAuthority(); 1226f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1227f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String legacyAuthority = "contacts"; 1228f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1229f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = new Intent(); 12305649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan resultIntent.setAction(Intent.ACTION_VIEW); 1231f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (legacyAuthority.equals(requestAuthority)) { 1232f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Build legacy Uri when requested by caller 1233f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(Contacts.lookupContact( 1234f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.getContentResolver(), contactLookupUri)); 1235f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyContentUri = Uri.parse("content://contacts/people"); 1236f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyUri = ContentUris.withAppendedId( 1237f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann legacyContentUri, contactId); 1238f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(legacyUri); 1239f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1240f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Otherwise pass back a lookup-style Uri 1241f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(contactLookupUri); 1242f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1243f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1244f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1245f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 1246f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1247825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // It is already saved, so prevent that it is saved again 1248825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 12495649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan if (mListener != null) mListener.onSaveFinished(resultIntent); 1250f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1251a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 125215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.RELOAD: 1253dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov case SaveMode.JOIN: 125436d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 1255623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann // If it was a JOIN, we are now ready to bring up the join activity. 1256e813f5e56ddc6395c5e08e9245e2c5ad41e91724Daniel Lehmann if (saveMode == SaveMode.JOIN && hasValidState()) { 1257623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann showJoinAggregateActivity(contactLookupUri); 1258623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann } 1259623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann 126015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If this was in INSERT, we are changing into an EDIT now. 126115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If it already was an EDIT, we are changing to the new Uri now 126244cfc56d1701629070384364416c1311b780535dChiao Cheng mState = new RawContactDeltaList(); 12631015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov load(Intent.ACTION_EDIT, contactLookupUri, null); 1264825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.LOADING; 126515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener); 126615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 126715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann break; 1268a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 126915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.SPLIT: 1270a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mStatus = Status.CLOSING; 1271a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann if (mListener != null) { 12728c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov mListener.onContactSplit(contactLookupUri); 1273a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } else { 1274a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann Log.d(TAG, "No listener registered, can not call onSplitFinished"); 1275a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1276f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1277f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1278f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1279f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1280f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1281f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 1282f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 1283f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 1284f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1285f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 128673a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov if (contactLookupUri == null || !isAdded()) { 1287f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 1288f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1289f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1290f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 1291623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = isContactWritable(); 1292f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = new Intent(JoinContactActivity.JOIN_CONTACT); 1293f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(JoinContactActivity.EXTRA_TARGET_CONTACT_ID, mContactIdForJoin); 1294a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_JOIN); 1295f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1296f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1297f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1298f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 1299f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1300f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 13012b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin, 1302623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann contactId, mContactWritableForJoin, 13032b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED); 13042b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov mContext.startService(intent); 1305f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1306f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1307f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1308ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov * Returns true if there is at least one writable raw contact in the current contact. 1309ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov */ 1310ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov private boolean isContactWritable() { 1311a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1312ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov int size = mState.size(); 1313ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov for (int i = 0; i < size; i++) { 1314851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDelta entity = mState.get(i); 1315851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final AccountType type = entity.getAccountType(accountTypes); 131696e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 1317ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return true; 1318ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1319ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1320ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return false; 1321ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1322ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov 13232bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson private boolean isEditingUserProfile() { 13242bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson return mNewLocalProfile || mIsUserProfile; 13252bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson } 13262bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson 1327cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public static interface Listener { 1328cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 132922fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was not found, so somehow close this fragment. This is raised after a contact 133022fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * is removed via Menu/Delete (unless it was a new contact) 1331cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 133222fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onContactNotFound(); 1333f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1334f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 13358c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov * Contact was split, so we can close now. 1336a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * @param newLookupUri The lookup uri of the new contact that should be shown to the user. 1337a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * The editor tries best to chose the most natural contact here. 1338f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 13398c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov void onContactSplit(Uri newLookupUri); 1340f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1341f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1342f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User has tapped Revert, close the fragment now. 1343f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 134422fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onReverted(); 1345f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1346f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 134722fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was saved and the Fragment can now be closed safely. 1348f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 13495649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan void onSaveFinished(Intent resultIntent); 1350b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann 1351b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann /** 1352e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * User switched to editing a different contact (a suggestion from the 1353e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * aggregation engine). 1354e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov */ 1355e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov void onEditOtherContactRequested( 1356e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov Uri contactLookupUri, ArrayList<ContentValues> contentValues); 1357fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1358fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1359fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * Contact is being created for an external account that provides its own 1360fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * new contact activity. 1361fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 13622b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro void onCustomCreateContactActivityRequested(AccountWithDataSet account, 13632b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro Bundle intentExtras); 1364fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1365fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1366fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * The edited raw contact belongs to an external account that provides 1367fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * its own edit activity. 1368fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * 1369fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * @param redirect indicates that the current editor should be closed 1370fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * before the custom editor is shown. 1371fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 13722b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro void onCustomEditContactActivityRequested(AccountWithDataSet account, Uri rawContactUri, 1373fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Bundle intentExtras, boolean redirect); 1374f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1375f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1376851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private class EntityDeltaComparator implements Comparator<RawContactDelta> { 1377f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1378f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Compare EntityDeltas for sorting the stack of editors. 1379f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 13804a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann @Override 1381851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public int compare(RawContactDelta one, RawContactDelta two) { 1382f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check direct equality 1383f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (one.equals(two)) { 1384f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 0; 1385f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1386f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1387a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 13882b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountType1 = one.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 13892b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet1 = one.getValues().getAsString(RawContacts.DATA_SET); 13902b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type1 = accountTypes.getAccountType(accountType1, dataSet1); 13912b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountType2 = two.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 13922b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet2 = two.getValues().getAsString(RawContacts.DATA_SET); 13932b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type2 = accountTypes.getAccountType(accountType2, dataSet2); 1394f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1395f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check read-only 139696e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (!type1.areContactsWritable() && type2.areContactsWritable()) { 1397f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 139896e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann } else if (type1.areContactsWritable() && !type2.areContactsWritable()) { 1399f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1400f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1401f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1402f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account type 1403f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean skipAccountTypeCheck = false; 1404b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount1 = type1 instanceof GoogleAccountType; 1405b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount2 = type2 instanceof GoogleAccountType; 140669f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (isGoogleAccount1 && !isGoogleAccount2) { 1407f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 140869f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (!isGoogleAccount1 && isGoogleAccount2) { 1409f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 141069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (isGoogleAccount1 && isGoogleAccount2){ 1411f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann skipAccountTypeCheck = true; 1412f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1413f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1414f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int value; 1415f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!skipAccountTypeCheck) { 1416b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (type1.accountType == null) { 14172776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru return 1; 14182776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru } 1419b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov value = type1.accountType.compareTo(type2.accountType); 1420f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1421f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 14222b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else { 14232b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro // Fall back to data set. 14242b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (type1.dataSet != null) { 14252b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro value = type1.dataSet.compareTo(type2.dataSet); 14262b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (value != 0) { 14272b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return value; 14282b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 14292b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else if (type2.dataSet != null) { 14302b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return 1; 14312b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 1432f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1433f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1434f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1435f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account name 1436851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String oneAccount = one.getAccountName(); 1437f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneAccount == null) oneAccount = ""; 1438851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu String twoAccount = two.getAccountName(); 1439f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (twoAccount == null) twoAccount = ""; 1440f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann value = oneAccount.compareTo(twoAccount); 1441f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1442f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 1443f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1444f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1445f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Both are in the same account, fall back to contact ID 1446851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu Long oneId = one.getRawContactId(); 1447851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu Long twoId = two.getRawContactId(); 1448f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneId == null) { 1449f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1450f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoId == null) { 1451f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1452f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1453f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1454f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return (int)(oneId - twoId); 1455f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1456f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1457f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1458f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1459f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Returns the contact ID for the currently edited contact or 0 if the contact is new. 1460f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1461f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected long getContactId() { 146244cfc56d1701629070384364416c1311b780535dChiao Cheng for (RawContactDelta rawContact : mState) { 146344cfc56d1701629070384364416c1311b780535dChiao Cheng Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID); 146444cfc56d1701629070384364416c1311b780535dChiao Cheng if (contactId != null) { 146544cfc56d1701629070384364416c1311b780535dChiao Cheng return contactId; 1466f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1467f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1468f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return 0; 1469f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1470f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1471f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1472f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Triggers an asynchronous search for aggregation suggestions. 1473f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 14742828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki private void acquireAggregationSuggestions(Context context, 14752828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki RawContactEditorView rawContactEditor) { 14769302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov long rawContactId = rawContactEditor.getRawContactId(); 14779302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (mAggregationSuggestionsRawContactId != rawContactId 14789302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov && mAggregationSuggestionView != null) { 14799302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 14809302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = null; 14819302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionEngine.reset(); 14829302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 14839302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 14849302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = rawContactId; 14859302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 1486f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine == null) { 14872828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki mAggregationSuggestionEngine = new AggregationSuggestionEngine(context); 1488f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.setListener(this); 1489f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.start(); 1490f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1491f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1492916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mAggregationSuggestionEngine.setContactId(getContactId()); 1493916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 1494392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann LabeledEditorView nameEditor = rawContactEditor.getNameEditor(); 1495f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.onNameChange(nameEditor.getValues()); 1496f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1497f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1498f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 1499f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onAggregationSuggestionChange() { 1500288532cddfccdc3793dd748d1c75750e2f46cb53Yorke Lee Activity activity = getActivity(); 1501288532cddfccdc3793dd748d1c75750e2f46cb53Yorke Lee if ((activity != null && activity.isFinishing()) 150244cfc56d1701629070384364416c1311b780535dChiao Cheng || !isVisible() || mState.isEmpty() || mStatus != Status.EDITING) { 150302cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov return; 150402cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov } 150502cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov 150686625158bdc52855c37e96bf098ba7a213c810d7Chiao Cheng UiClosables.closeQuietly(mAggregationSuggestionPopup); 1507f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 15086c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) { 1509f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 1510f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1511f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 15126c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final RawContactEditorView rawContactView = 15136c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId); 151402a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki if (rawContactView == null) { 151502a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki return; // Raw contact deleted? 151602a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki } 15176c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final View anchorView = rawContactView.findViewById(R.id.anchor_view); 15186c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = new ListPopupWindow(mContext, null); 15196c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAnchorView(anchorView); 15206c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setWidth(anchorView.getWidth()); 15216c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 15226c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAdapter( 15236c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new AggregationSuggestionAdapter(getActivity(), 15246c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mState.size() == 1 && mState.get(0).isContactInsert(), 15256c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa this, mAggregationSuggestionEngine.getSuggestions())); 15266c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setOnItemClickListener(mAggregationSuggestionItemClickListener); 15276c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.show(); 1528bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1529bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1530bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1531bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onJoinAction(long contactId, List<Long> rawContactIdList) { 1532bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = new long[rawContactIdList.size()]; 1533bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov for (int i = 0; i < rawContactIds.length; i++) { 1534bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov rawContactIds[i] = rawContactIdList.get(i); 1535bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1536bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov JoinSuggestedContactDialogFragment dialog = 1537bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new JoinSuggestedContactDialogFragment(); 1538bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1539bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putLongArray("rawContactIds", rawContactIds); 1540bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1541bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 154274f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov try { 154374f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov dialog.show(getFragmentManager(), "join"); 154474f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } catch (Exception ex) { 154574f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov // No problem - the activity is no longer available to display the dialog 154674f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } 1547bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1548bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1549bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class JoinSuggestedContactDialogFragment extends DialogFragment { 1550bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1551bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1552bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1553bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 15544292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1555bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_join_dialog_message) 1556bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1557bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1558f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 1559bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1560bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1561bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1562bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = 1563bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getLongArray("rawContactIds"); 1564bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doJoinSuggestedContact(rawContactIds); 1565bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1566bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1567bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1568bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1569bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1570bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1571bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1572bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1573bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1574bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Joins the suggested contact (specified by the id's of constituent raw 1575bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * contacts), save all changes, and stay in the editor. 1576bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1577bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doJoinSuggestedContact(long[] rawContactIds) { 1578cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1579cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov return; 1580cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov } 1581cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov 1582bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mState.setJoinWithRawContacts(rawContactIds); 15839df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 1584bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1585bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1586bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1587bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onEditAction(Uri contactLookupUri) { 1588bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov SuggestionEditConfirmationDialogFragment dialog = 1589bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new SuggestionEditConfirmationDialogFragment(); 1590bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1591bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putParcelable("contactUri", contactLookupUri); 1592bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1593bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 1594bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.show(getFragmentManager(), "edit"); 1595bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1596bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1597bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class SuggestionEditConfirmationDialogFragment extends DialogFragment { 1598bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1599bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1600bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1601bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 16024292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1603bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_edit_dialog_message) 1604bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1605bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1606f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 1607bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1608bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1609bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1610bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Uri contactUri = 1611bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getParcelable("contactUri"); 1612bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doEditSuggestedContact(contactUri); 1613bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1614bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1615bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1616bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1617bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1618bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1619bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1620bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1621bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1622bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Abandons the currently edited contact and switches to editing the suggested 1623bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * one, transferring all the data there 1624bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1625bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doEditSuggestedContact(Uri contactUri) { 1626bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov if (mListener != null) { 1627a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann // make sure we don't save this contact when closing down 1628a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann mStatus = Status.CLOSING; 1629bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mListener.onEditOtherContactRequested( 1630bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov contactUri, mState.get(0).getContentValues()); 1631bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1632bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1633bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1634a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov public void setAggregationSuggestionViewEnabled(boolean enabled) { 1635a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (mAggregationSuggestionView == null) { 1636a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov return; 1637a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1638a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1639a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 1640a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov R.id.aggregation_suggestions); 1641a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov int count = itemList.getChildCount(); 1642a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov for (int i = 0; i < count; i++) { 1643a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov itemList.getChildAt(i).setEnabled(enabled); 1644a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1645a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1646a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1647f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1648f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 1649b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann outState.putParcelable(KEY_URI, mLookupUri); 1650d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putString(KEY_ACTION, mAction); 1651d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 1652f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (hasValidState()) { 1653f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Store entities with modifications 1654f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_EDIT_STATE, mState); 1655f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 16564bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 1657f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator); 1658637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee outState.putParcelable(KEY_CURRENT_PHOTO_URI, mCurrentPhotoUri); 1659f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 1660623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin); 16619302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov outState.putLong(KEY_SHOW_JOIN_SUGGESTIONS, mAggregationSuggestionsRawContactId); 166202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov outState.putBoolean(KEY_ENABLED, mEnabled); 1663ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile); 1664ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile); 1665ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov outState.putInt(KEY_STATUS, mStatus); 166628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos); 166744cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact); 166844cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_IS_EDIT, mIsEdit); 166944cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady); 167044cfc56d1701629070384364416c1311b780535dChiao Cheng outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady); 167113d52b10fd720bb94ffe7a7e7ad1b37c1e06bb50Yorke Lee outState.putParcelableArrayList(KEY_RAW_CONTACTS, 167213d52b10fd720bb94ffe7a7e7ad1b37c1e06bb50Yorke Lee mRawContacts == null ? 167313d52b10fd720bb94ffe7a7e7ad1b37c1e06bb50Yorke Lee Lists.<RawContact> newArrayList() : Lists.newArrayList(mRawContacts)); 167428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 1675f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 1676f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1677f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1678d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 1679f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 1680f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (mStatus == Status.SUB_ACTIVITY) { 1681f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.EDITING; 1682f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov } 1683f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 16846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // See if the photo selection handler handles this result. 168591004b37683c15650eccde68ff04defcf94a1c84Maurice Chu if (mCurrentPhotoHandler != null && mCurrentPhotoHandler.handlePhotoActivityResult( 16866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro requestCode, resultCode, data)) { 16876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return; 16886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 16906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro switch (requestCode) { 1691a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_JOIN: { 16920353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Ignore failed requests 16930353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) return; 1694f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 1695f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 1696f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 1697f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 16984a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann break; 1699f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 17000353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan case REQUEST_CODE_ACCOUNTS_CHANGED: { 17010353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Bail if the account selector was not successful. 17020353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) { 17030353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mListener.onReverted(); 17040353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 17050353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 17060353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there's an account specified, use it. 17070353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (data != null) { 17080353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet account = data.getParcelableExtra(Intents.Insert.ACCOUNT); 17090353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (account != null) { 17100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(account); 17110353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 17120353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 17130353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 17140353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there isn't an account specified, then this is likely a phone-local 17150353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // contact, so we should continue setting up the editor by automatically selecting 17160353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // the most appropriate account. 17170353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(); 17180353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan break; 17190353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 1720f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1721cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 17229cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 1723c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann /** 1724c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann * Sets the photo stored in mPhoto and writes it to the RawContact with the given id 1725c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann */ 1726637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee private void setPhoto(long rawContact, Bitmap photo, Uri photoUri) { 1727bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact); 1728e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1729e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus if (photo == null || photo.getHeight() < 0 || photo.getWidth() < 0) { 1730e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus // This is unexpected. 1731e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus Log.w(TAG, "Invalid bitmap passed to setPhoto()"); 1732e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus } 1733e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 17349302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestingEditor != null) { 17359302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov requestingEditor.setPhotoBitmap(photo); 17369302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } else { 17379302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Log.w(TAG, "The contact that requested the photo is no longer present."); 17389302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1739e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1740637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mUpdatedPhotos.putParcelable(String.valueOf(rawContact), photoUri); 17419302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 17429302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 17439302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov /** 17449302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov * Finds raw contact editor view for the given rawContactId. 17459302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov */ 1746bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public BaseRawContactEditorView getRawContactEditorView(long rawContactId) { 1747c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 1748c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann final View childView = mContent.getChildAt(i); 174972af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 175072af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 17519302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (editor.getRawContactId() == rawContactId) { 17529302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return editor; 1753c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1754c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1755c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 17569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return null; 1757c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1758c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1759fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 1760fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann * Returns true if there is currently more than one photo on screen. 1761fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1762fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann private boolean hasMoreThanOnePhoto() { 1763fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int countWithPicture = 0; 176491004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final int numEntities = mState.size(); 176591004b37683c15650eccde68ff04defcf94a1c84Maurice Chu for (int i = 0; i < numEntities; i++) { 1766851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final RawContactDelta entity = mState.get(i); 1767851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (entity.isVisible()) { 176891004b37683c15650eccde68ff04defcf94a1c84Maurice Chu final ValuesDelta primary = entity.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE); 1769851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (primary != null && primary.getPhoto() != null) { 1770fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann countWithPicture++; 177191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } else { 1772851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final long rawContactId = entity.getRawContactId(); 1773637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee final Uri uri = mUpdatedPhotos.getParcelable(String.valueOf(rawContactId)); 1774637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee if (uri != null) { 1775637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee try { 1776637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mContext.getContentResolver().openInputStream(uri); 177791004b37683c15650eccde68ff04defcf94a1c84Maurice Chu countWithPicture++; 1778637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee } catch (FileNotFoundException e) { 177991004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 178091004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 178191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu } 178291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu 178391004b37683c15650eccde68ff04defcf94a1c84Maurice Chu if (countWithPicture > 1) { 178491004b37683c15650eccde68ff04defcf94a1c84Maurice Chu return true; 1785fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1786fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1787fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1788fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann return false; 17899cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1790222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1791222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann /** 1792222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann * The listener for the data loader 1793222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann */ 1794851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private final LoaderManager.LoaderCallbacks<Contact> mDataLoaderListener = 1795851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 1796222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1797851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 1798222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann mLoaderStartTime = SystemClock.elapsedRealtime(); 179945ee872fe7be69c6b3f0c59167eecd11af467812Makoto Onuki return new ContactLoader(mContext, mLookupUri, true); 1800222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1801222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1802222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1803851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 1804222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long loaderCurrentTime = SystemClock.elapsedRealtime(); 1805222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime)); 18062621c5bb7049401c8bce740005fa60bf1b304b86Makoto Onuki if (!data.isLoaded()) { 1807222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann // Item has been deleted 1808222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.i(TAG, "No contact found. Closing activity"); 180922fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onContactNotFound(); 1810222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return; 1811222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1812222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1813825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.EDITING; 18146caccaeeed943db323be89853a108f422e670760Dmitri Plotnikov mLookupUri = data.getLookupUri(); 1815222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataStartTime = SystemClock.elapsedRealtime(); 1816222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann setData(data); 1817222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataEndTime = SystemClock.elapsedRealtime(); 1818c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1819222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime)); 1820222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 18214ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1822623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann @Override 1823851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 18244ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1825222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann }; 1826a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 1827e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov /** 1828be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan * The listener for the group meta data loader for all groups. 1829e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov */ 1830e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener = 1831e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov new LoaderCallbacks<Cursor>() { 1832e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1833e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1834e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public CursorLoader onCreateLoader(int id, Bundle args) { 1835be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI); 1836e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1837e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1838e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1839e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1840e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov mGroupMetaData = data; 1841e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 1842e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 18434ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1844f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 18454ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 18464ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1847e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov }; 1848e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1849a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann @Override 1850a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann public void onSplitContactConfirmed() { 185144cfc56d1701629070384364416c1311b780535dChiao Cheng if (mState.isEmpty()) { 1852b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // This may happen when this Fragment is recreated by the system during users 1853b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // confirming the split action (and thus this method is called just before onCreate()), 1854b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // for example. 1855b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa Log.e(TAG, "mState became null during the user's confirming split action. " + 1856b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa "Cannot perform the save action."); 1857b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa return; 1858b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa } 1859b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa 1860a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann mState.markRawContactsForSplitting(); 18619df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.SPLIT); 1862a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1863a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 18646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 18656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Custom photo handler for the editor. The inner listener that this creates also has a 18666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * reference to the editor and acts as an {@link EditorListener}, and uses that editor to hold 18676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * state information in several of the listener methods. 18686fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 18696fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoHandler extends PhotoSelectionHandler { 187028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 187128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus final long mRawContactId; 1872e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus private final BaseRawContactEditorView mEditor; 18734bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki private final PhotoActionListener mPhotoEditorListener; 187428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 18756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode, 1876851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactDeltaList state) { 18776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro super(context, editor.getPhotoEditor(), photoMode, false, state); 1878e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mEditor = editor; 187928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mRawContactId = editor.getRawContactId(); 18809a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann mPhotoEditorListener = new PhotoEditorListener(); 1881e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1882e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1883e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1884e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus public PhotoActionListener getListener() { 18859a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann return mPhotoEditorListener; 1886e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1887e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1888e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1889637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) { 18904bff8fb686f2ac5500109a32cca9270965c620d6Makoto Onuki mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 189191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu mCurrentPhotoHandler = this; 1892e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mStatus = Status.SUB_ACTIVITY; 1893637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee mCurrentPhotoUri = photoUri; 1894e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus ContactEditorFragment.this.startActivityForResult(intent, requestCode); 18959442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 18969442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 18976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener 18986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro implements EditorListener { 1899fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 19006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRequest(int request) { 19026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (!hasValidState()) return; 1903a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 19046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (request == EditorListener.REQUEST_PICK_PHOTO) { 19056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro onClick(mEditor.getPhotoEditor()); 19069442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 19079442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1908a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 19096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onDeleteRequested(Editor removedEditor) { 19116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // The picture cannot be deleted, it can only be removed, which is handled by 19126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // onRemovePictureChosen() 19136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1914a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 19156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 19166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to set the selected photo as the (super) primary photo 19176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 19186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onUseAsPrimaryChosen() { 19206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set the IsSuperPrimary for each editor 19216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro int count = mContent.getChildCount(); 19226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro for (int i = 0; i < count; i++) { 19236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final View childView = mContent.getChildAt(i); 19246fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (childView instanceof BaseRawContactEditorView) { 19256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final BaseRawContactEditorView editor = 19266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro (BaseRawContactEditorView) childView; 19276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final PhotoEditorView photoEditor = editor.getPhotoEditor(); 19286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro photoEditor.setSuperPrimary(editor == mEditor); 19296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 193191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 19326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19339442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 19346fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 19356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to remove a picture 19366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 19376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRemovePictureChosen() { 19396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro mEditor.setPhotoBitmap(null); 194028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 194128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // Prevent bitmap from being restored if rotate the device. 194228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // (only if we first chose a new photo before removing it) 194328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mUpdatedPhotos.remove(String.valueOf(mRawContactId)); 194491004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 19456fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 19476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 1948637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public void onPhotoSelected(Uri uri) throws FileNotFoundException { 1949637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(mContext, uri); 1950637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee setPhoto(mRawContactId, bitmap, uri); 195191004b37683c15650eccde68ff04defcf94a1c84Maurice Chu mCurrentPhotoHandler = null; 195291004b37683c15650eccde68ff04defcf94a1c84Maurice Chu bindEditors(); 19536fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19546fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 19556fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 1956637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee public Uri getCurrentPhotoUri() { 1957637a38ec9de6b1f434d7a13105f2e747faae5107Yorke Lee return mCurrentPhotoUri; 19586fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 19596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 19606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 19616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onPhotoSelectionDismissed() { 19626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Nothing to do. 19639442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 19644a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 19654a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 19662ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1967