ContactEditorFragment.java revision 740552201d103b80bc49ea8a39a30536222672ea
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 1918ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.ContactLoader; 2018ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.ContactSaveService; 2118ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.GroupMetaDataLoader; 22cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport com.android.contacts.R; 230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuanimport com.android.contacts.activities.ContactEditorAccountsChangedActivity; 242b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikovimport com.android.contacts.activities.ContactEditorActivity; 25d21ddb2c96e71f43eaf7addc25e163181d1ca87dDmitri Plotnikovimport com.android.contacts.activities.JoinContactActivity; 266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.detail.PhotoSelectionHandler; 2718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; 2818ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.Editor.EditorListener; 294597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType; 30a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikovimport com.android.contacts.model.AccountTypeManager; 312b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoroimport com.android.contacts.model.AccountWithDataSet; 32f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityDelta; 33f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityDelta.ValuesDelta; 34ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmannimport com.android.contacts.model.EntityDeltaList; 35f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityModifier; 3635769b804fbfd5a1fc0b2c36cd0a786d662c4334Daniel Lehmannimport com.android.contacts.model.GoogleAccountType; 37d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.util.AccountsListAdapter; 386f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onukiimport com.android.contacts.util.AccountsListAdapter.AccountListFilter; 39692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chuimport com.android.contacts.util.HelpUtils; 40f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 41f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.accounts.Account; 42cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity; 43bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.AlertDialog; 44bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.Dialog; 45bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.DialogFragment; 46222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.Fragment; 47222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager; 48222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 49cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 50cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentValues; 51cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 52e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikovimport android.content.CursorLoader; 53bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface; 54e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikovimport android.content.Entity; 55cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 56cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader; 57f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor; 58f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 5928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargusimport android.graphics.BitmapFactory; 60cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 61cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 629767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock; 63cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 64362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Event; 65362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Organization; 66cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 67362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 68f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 69be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuanimport android.provider.ContactsContract.Groups; 702013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmannimport android.provider.ContactsContract.Intents; 71f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 72cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 73cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 74cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu; 75cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater; 76cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem; 77cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 78cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 79d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.AdapterView; 806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener; 816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.BaseAdapter; 8280d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 83d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.ListPopupWindow; 84cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast; 85cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 86f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.io.File; 87cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport java.util.ArrayList; 88f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections; 89f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Comparator; 90f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List; 91f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 92a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmannpublic class ContactEditorFragment extends Fragment implements 93d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa SplitContactConfirmationDialogFragment.Listener, 94fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener, 952b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann RawContactReadOnlyEditorView.Listener { 96cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 972245870a1354df03512010e4968b144840894fb7Frank Sposaro private static final String TAG = ContactEditorFragment.class.getSimpleName(); 98cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 99f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int LOADER_DATA = 1; 100e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private static final int LOADER_GROUPS = 2; 101f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 102d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_URI = "uri"; 103d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_ACTION = "action"; 104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_EDIT_STATE = "state"; 105f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester"; 106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator"; 107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CURRENT_PHOTO_FILE = "currentphotofile"; 108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin"; 109623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin"; 1109302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions"; 11102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private static final String KEY_ENABLED = "enabled"; 112ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov private static final String KEY_STATUS = "status"; 113ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile"; 114ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private static final String KEY_IS_USER_PROFILE = "isUserProfile"; 11528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus private static final String KEY_UPDATED_PHOTOS = "updatedPhotos"; 116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 117a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public static final String SAVE_MODE_EXTRA_KEY = "saveMode"; 118a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 11915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 1207d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * An intent extra that forces the editor to add the edited contact 1217d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * to the default group (e.g. "My Contacts"). 1227d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov */ 1237d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory"; 1247d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 125ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile"; 126ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 1277d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov /** 12815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Modes that specify what the AsyncTask has to perform after saving 12915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 1309df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public interface SaveMode { 13115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 13215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Close the editor after saving 13315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 13415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int CLOSE = 0; 13515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 13615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 13715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Reload the data so that the user can continue editing 13815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 13915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int RELOAD = 1; 14015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 14115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 14215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Split the contact after saving 14315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int SPLIT = 2; 14515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 14615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 14715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Join another contact after saving 14815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int JOIN = 3; 1509df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov 1519df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov /** 1529df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov * Navigate to Contacts Home activity after saving. 1539df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov */ 1549df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public static final int HOME = 4; 15515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 156a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 157825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private interface Status { 158825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 159825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * The loader is fetching data 160825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 161825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int LOADING = 0; 162825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 163825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 164825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * Not currently busy. We are waiting for the user to enter data 165825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 166825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int EDITING = 1; 167825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 168825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 169f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * The data is currently being saved. This is used to prevent more 170f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * auto-saves (they shouldn't overlap) 171825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 172825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int SAVING = 2; 173825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 174825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 175a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * Prevents any more saves. This is used if in the following cases: 176a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After Save/Close 177a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After Revert 178a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After the user has accepted an edit suggestion 179825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 180825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int CLOSING = 3; 181f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 182f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov /** 183f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * Prevents saving while running a child activity. 184f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov */ 185f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov public static final int SUB_ACTIVITY = 4; 186825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 187825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 188a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_JOIN = 0; 1896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1; 190f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 191f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mRawContactIdRequestingPhoto = -1; 1926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private PhotoSelectionHandler mPhotoSelectionHandler; 193cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 194f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private final EntityDeltaComparator mComparator = new EntityDeltaComparator(); 195f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 196e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private Cursor mGroupMetaData; 197e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 198f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private File mCurrentPhotoFile; 19928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus private Bundle mUpdatedPhotos = new Bundle(); 200cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 201cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Context mContext; 202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mAction; 203b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann private Uri mLookupUri; 204f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Bundle mIntentExtras; 205cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Listener mListener; 206cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 207f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mContactIdForJoin; 208623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann private boolean mContactWritableForJoin; 209cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 2100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private ContactEditorUtils mEditorUtils; 2110353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 212f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private LinearLayout mContent; 213ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann private EntityDeltaList mState; 214cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 215f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 216cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 2179767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann private long mLoaderStartTime; 2189767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann 219825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private int mStatus; 220825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 221f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private AggregationSuggestionEngine mAggregationSuggestionEngine; 2229302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private long mAggregationSuggestionsRawContactId; 2239302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private View mAggregationSuggestionView; 224f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 2256c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private ListPopupWindow mAggregationSuggestionPopup; 2266c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2276c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private static final class AggregationSuggestionAdapter extends BaseAdapter { 2286c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final Activity mActivity; 2296c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final boolean mSetNewContact; 2306c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final AggregationSuggestionView.Listener mListener; 2316c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final List<Suggestion> mSuggestions; 2326c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2336c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public AggregationSuggestionAdapter(Activity activity, boolean setNewContact, 2346c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) { 2356c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mActivity = activity; 2366c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSetNewContact = setNewContact; 2376c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mListener = listener; 2386c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSuggestions = suggestions; 2396c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2406c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2416c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2426c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 2436c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa Suggestion suggestion = (Suggestion) getItem(position); 2446c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa LayoutInflater inflater = mActivity.getLayoutInflater(); 2456c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView suggestionView = 2466c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (AggregationSuggestionView) inflater.inflate( 2476c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa R.layout.aggregation_suggestions_item, null); 2486c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setNewContact(mSetNewContact); 2496c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setListener(mListener); 2506c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.bindSuggestion(suggestion); 2516c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return suggestionView; 2526c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2536c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2546c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2556c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public long getItemId(int position) { 2566c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return position; 2576c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2586c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2596c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2606c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public Object getItem(int position) { 2616c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.get(position); 2626c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2636c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2646c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2656c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public int getCount() { 2666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.size(); 2676c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2686c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2696c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private OnItemClickListener mAggregationSuggestionItemClickListener = 2716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new OnItemClickListener() { 2726c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2736c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 2746c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view; 2756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.handleItemClickEvent(); 2766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.dismiss(); 2776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = null; 2786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa }; 2806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2817d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov private boolean mAutoAddToDefaultGroup; 2827d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 28302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private boolean mEnabled = true; 284eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov private boolean mRequestFocus; 285ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private boolean mNewLocalProfile = false; 286ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private boolean mIsUserProfile = false; 28702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 288cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 289cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 290cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 29102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public void setEnabled(boolean enabled) { 29202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mEnabled != enabled) { 29302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = enabled; 29402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mContent != null) { 29502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int count = mContent.getChildCount(); 29602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < count; i++) { 29702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mContent.getChildAt(i).setEnabled(enabled); 29802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 29902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 300a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov setAggregationSuggestionViewEnabled(enabled); 30102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov final Activity activity = getActivity(); 30202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (activity != null) activity.invalidateOptionsMenu(); 30302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 30402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 30502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 306cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 307cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public void onAttach(Activity activity) { 308cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann super.onAttach(activity); 309cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann mContext = activity; 3100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils = ContactEditorUtils.getInstance(mContext); 311cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 312cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 313cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 314f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onStop() { 315f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super.onStop(); 316f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine != null) { 317f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.quit(); 318f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 319248fba273e867616b1f8973dac6ce3e5ee1ba544Dmitri Plotnikov 320825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If anything was left unsaved, save it now but keep the editor open. 321f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) { 322623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann save(SaveMode.RELOAD); 323825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 324f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 325f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 326f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 327cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 328cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 329cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 330f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 331e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 3323648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 333cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 334825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If we are in an orientation change, we already have mState (it was loaded by onCreate) 335825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (mState != null) { 336825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann bindEditors(); 337825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 338825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 339cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 340cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 341cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 342222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 343222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onActivityCreated(Bundle savedInstanceState) { 344222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann super.onActivityCreated(savedInstanceState); 345222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 346825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Handle initial actions only when existing state missing 3474a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann final boolean hasIncomingState = savedInstanceState != null; 348825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 349825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (!hasIncomingState) { 350825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (Intent.ACTION_EDIT.equals(mAction)) { 351825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener); 352825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } else if (Intent.ACTION_INSERT.equals(mAction)) { 3532013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann final Account account = mIntentExtras == null ? null : 3542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT); 3552b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = mIntentExtras == null ? null : 3562b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mIntentExtras.getString(Intents.Insert.DATA_SET); 3572013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann 3582013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann if (account != null) { 3592013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // Account specified in Intent 3602b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro createContact(new AccountWithDataSet(account.name, account.type, dataSet)); 3612013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } else { 3622013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // No Account specified. Let the user choose 36340bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov // Load Accounts async so that we can present them 3640353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan selectAccountAndCreateContact(); 3652013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } 366a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else if (ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(mAction)) { 367a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov // do nothing 368825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } else throw new IllegalArgumentException("Unknown Action String " + mAction + 369825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT); 370825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 371222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 372222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 373e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 374e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onStart() { 375e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener); 376e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov super.onStart(); 377e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 378e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 3791015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov public void load(String action, Uri lookupUri, Bundle intentExtras) { 380f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mAction = action; 381b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = lookupUri; 382f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mIntentExtras = intentExtras; 3837d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov mAutoAddToDefaultGroup = mIntentExtras != null 3847d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY); 385ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = mIntentExtras != null 38636d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro && mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE); 387f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 388f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 389f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void setListener(Listener value) { 390f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener = value; 391cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 392cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 393cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 394f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 395d364314c460152db7089b304beec81b3675893baDmitri Plotnikov if (savedState != null) { 396d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // Restore mUri before calling super.onCreate so that onInitializeLoaders 397d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // would already have a uri and an action to work with 398b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = savedState.getParcelable(KEY_URI); 399d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mAction = savedState.getString(KEY_ACTION); 400d364314c460152db7089b304beec81b3675893baDmitri Plotnikov } 401d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 402f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 403f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 404f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (savedState == null) { 405f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If savedState is non-null, onRestoreInstanceState() will restore the generator. 406f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = new ViewIdGenerator(); 407f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 408825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Read state from savedState. No loading involved here 409ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = savedState.<EntityDeltaList> getParcelable(KEY_EDIT_STATE); 410f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactIdRequestingPhoto = savedState.getLong( 411f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 412f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR); 413f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String fileName = savedState.getString(KEY_CURRENT_PHOTO_FILE); 414f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (fileName != null) { 415f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mCurrentPhotoFile = new File(fileName); 416cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 417f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 418623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN); 4199302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = savedState.getLong(KEY_SHOW_JOIN_SUGGESTIONS); 42002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = savedState.getBoolean(KEY_ENABLED); 421ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov mStatus = savedState.getInt(KEY_STATUS); 422ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE); 423ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE); 42428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS); 425cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 426cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 427cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 428bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann public void setData(ContactLoader.Result data) { 429d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann // If we have already loaded data, we do not want to change it here to not confuse the user 430d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann if (mState != null) { 431d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann Log.v(TAG, "Ignoring background change. This will have to be rebased later"); 432d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann return; 433d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann } 434d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann 435fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov // See if this edit operation needs to be redirected to a custom editor 436fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ArrayList<Entity> entities = data.getEntities(); 437fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (entities.size() == 1) { 438fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Entity entity = entities.get(0); 439fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentValues entityValues = entity.getEntityValues(); 440fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE); 4412b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet = entityValues.getAsString(RawContacts.DATA_SET); 4422b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType( 4432b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro type, dataSet); 4442b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (accountType.getEditContactActivityClassName() != null && 4452b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann !accountType.areContactsWritable()) { 446fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 447fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov String name = entityValues.getAsString(RawContacts.ACCOUNT_NAME); 448fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID); 4492b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mListener.onCustomEditContactActivityRequested( 4502b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro new AccountWithDataSet(name, type, dataSet), 451fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 452fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mIntentExtras, true); 453fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 454fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov return; 455fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 456fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 457fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 458fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov bindEditorsForExistingContact(data); 459fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 460fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 461fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov @Override 4622b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public void onExternalEditorRequest(AccountWithDataSet account, Uri uri) { 463fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(account, uri, null, false); 464fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 465fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 466e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus private void bindEditorsForExistingContact(ContactLoader.Result contact) { 46702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov setEnabled(true); 46802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 469e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mState = contact.createEntityDeltaList(); 4701ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov setIntentExtras(mIntentExtras); 4711ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov mIntentExtras = null; 472e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikov 473ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // For user profile, change the contacts query URI 474e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mIsUserProfile = contact.isUserProfile(); 47548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson boolean localProfileExists = false; 47648ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson 477ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mIsUserProfile) { 478ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson for (EntityDelta state : mState) { 47948ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // For profile contacts, we need a different query URI 480ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson state.setProfileQueryUri(); 48148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // Try to find a local profile contact 48248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson if (state.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) { 48348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson localProfileExists = true; 48448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson } 48548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson } 48648ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson // Editor should always present a local profile for editing 48748ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson if (!localProfileExists) { 48848ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson final ContentValues values = new ContentValues(); 48948ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson values.putNull(RawContacts.ACCOUNT_NAME); 49048ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson values.putNull(RawContacts.ACCOUNT_TYPE); 49148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson values.putNull(RawContacts.DATA_SET); 49248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values)); 49348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson insert.setProfileQueryUri(); 49448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson mState.add(insert); 495ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 496ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 497eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 498eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 4991ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov bindEditors(); 5001ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 5011ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov 5021ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov /** 5031ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov * Merges extras from the intent. 5041ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov */ 5051ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov public void setIntentExtras(Bundle extras) { 5061ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov if (extras == null || extras.size() == 0) { 5071ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov return; 508bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 509916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 510a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 5111ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov for (EntityDelta state : mState) { 5121ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov final String accountType = state.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 5132b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = state.getValues().getAsString(RawContacts.DATA_SET); 5142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type = accountTypes.getAccountType(accountType, dataSet); 51596e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 5161ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov // Apply extras to the first writable raw contact only 51769f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.parseExtras(mContext, type, state, extras); 5181ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov break; 5191ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 5201ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 521f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 522cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 5230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void selectAccountAndCreateContact() { 5240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If this is a local profile, then skip the logic about showing the accounts changed 5250353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // activity and create a phone-local contact. 5260353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (mNewLocalProfile) { 5270353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(null); 5280353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 5290353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 5300353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 5310353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there is no default account or the accounts have changed such that we need to 5320353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // prompt the user again, then launch the account prompt. 5330353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (mEditorUtils.shouldShowAccountChangedNotification()) { 5340353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class); 5350353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mStatus = Status.SUB_ACTIVITY; 5360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED); 5370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } else { 5380353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Otherwise, there should be a default account. Then either create a local contact 5390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // (if default account is null) or create a contact with the specified account. 5400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet defaultAccount = mEditorUtils.getDefaultAccount(); 5410353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (defaultAccount == null) { 5420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(null); 5430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } else { 5440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(defaultAccount); 5450353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 5460353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 5470353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 5480353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 549d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 5500353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan * Create a contact by automatically selecting the first account. If there's no available 5510353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan * account, a device-local contact should be created. 552d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 553d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void createContact() { 5542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 555a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov AccountTypeManager.getInstance(mContext).getAccounts(true); 5560353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // No Accounts available. Create a phone-local contact. 5570353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (accounts.isEmpty()) { 55840bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(null); 5590353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 560f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 561cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 562d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // We have an account switcher in "create-account" screen, so don't need to ask a user to 563d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // select an account here. 564d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa createContact(accounts.get(0)); 565cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 566cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 567cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 568d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Shows account creation screen associated with a given account. 569d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 570d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param account may be null to signal a device-local contact should be created. 571cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 5722b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void createContact(AccountWithDataSet account) { 573a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 574b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType accountType = 5752b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro accountTypes.getAccountType(account != null ? account.type : null, 5762b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro account != null ? account.dataSet : null); 577fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 578b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (accountType.getCreateContactActivityClassName() != null) { 579fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 580fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomCreateContactActivityRequested(account, mIntentExtras); 581fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 582fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 583b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov bindEditorsForNewContact(account, accountType); 584fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 585fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 586fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 587d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 588d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Removes a current editor ({@link #mState}) and rebinds new editor for a new account. 589d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Some of old data are reused with new restriction enforced by the new account. 590d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 5912b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro * @param oldState Old data being edited. 592d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param oldAccount Old account associated with oldState. 593d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param newAccount New account to be used. 594d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 595d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void rebindEditorsForNewContact( 5962b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro EntityDelta oldState, AccountWithDataSet oldAccount, AccountWithDataSet newAccount) { 597d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 5982b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType oldAccountType = accountTypes.getAccountType( 5992b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro oldAccount.type, oldAccount.dataSet); 6002b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType newAccountType = accountTypes.getAccountType( 6012b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro newAccount.type, newAccount.dataSet); 602d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 603d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccountType.getCreateContactActivityClassName() != null) { 604d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa Log.w(TAG, "external activity called in rebind situation"); 605d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (mListener != null) { 606d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras); 607d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 608d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 609d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mState = null; 610d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType); 611d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 612d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 613d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 6142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet account, 6152b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType accountType) { 616d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(account, accountType, null, null); 617d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 618d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 6192b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet newAccount, 6202b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType newAccountType, EntityDelta oldState, AccountType oldAccountType) { 621a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov mStatus = Status.EDITING; 622a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 623f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentValues values = new ContentValues(); 624d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccount != null) { 625d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa values.put(RawContacts.ACCOUNT_NAME, newAccount.name); 626d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa values.put(RawContacts.ACCOUNT_TYPE, newAccount.type); 6272b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.put(RawContacts.DATA_SET, newAccount.dataSet); 628f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 629f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_NAME); 630f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_TYPE); 6312b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.putNull(RawContacts.DATA_SET); 632cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 633cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 634f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values)); 635d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (oldState == null) { 636d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // Parse any values from incoming intent 637d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras); 638d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 639d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.migrateStateForNewContact(mContext, oldState, insert, 640d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa oldAccountType, newAccountType); 641d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 642f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 64369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov // Ensure we have some default fields (if the account type does not support a field, 644362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmann // ensureKind will not add it, so it is safe to add e.g. Event) 645d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE); 646d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE); 647d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE); 648d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE); 649d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, StructuredPostal.CONTENT_ITEM_TYPE); 650f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 651ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // Set the correct URI for saving the contact as a profile 652ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mNewLocalProfile) { 653ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson insert.setProfileQueryUri(); 654ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 655ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 656f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mState == null) { 657f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Create state if none exists yet 658ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = EntityDeltaList.fromSingle(insert); 659f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 660f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add contact onto end of existing state 661f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mState.add(insert); 662cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 663f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 664eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 665eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 666f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 667cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 668cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 669f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void bindEditors() { 670f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 671f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 672cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 673f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 674f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 675cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 676f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 677f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 678a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 679a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan int numRawContacts = mState.size(); 680a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan for (int i = 0; i < numRawContacts; i++) { 681f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 682f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final EntityDelta entity = mState.get(i); 683f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ValuesDelta values = entity.getValues(); 684f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!values.isVisible()) continue; 685f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 686f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 6872b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = values.getAsString(RawContacts.DATA_SET); 6882b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type = accountTypes.getAccountType(accountType, dataSet); 689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long rawContactId = values.getAsLong(RawContacts._ID); 690f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 69172af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor; 6922b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann if (!type.areContactsWritable()) { 693fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov editor = (BaseRawContactEditorView) inflater.inflate( 6942b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann R.layout.raw_contact_readonly_editor_view, mContent, false); 6952b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann ((RawContactReadOnlyEditorView) editor).setListener(this); 696fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 697fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view, 698fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mContent, false); 699cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 700a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan if (Intent.ACTION_INSERT.equals(mAction) && numRawContacts == 1) { 7012b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 702d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager.getInstance(mContext).getAccounts(true); 703ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (accounts.size() > 1 && !mNewLocalProfile) { 704d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa addAccountSwitcher(mState.get(0), editor); 705a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan } else { 706a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan disableAccountSwitcher(editor); 707d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 708a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan } else { 709a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan disableAccountSwitcher(editor); 710d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 711a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan 71202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov editor.setEnabled(mEnabled); 713cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 714f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 7157d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 716681f36cc7cc49be781eedc4685eda2d1b2c0444cIsaac Katzenelson editor.setState(entity, type, mViewIdGenerator, isEditingUserProfile()); 717f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 7186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set up the photo handler. 7196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro bindPhotoHandler(editor, type, mState); 7206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 72128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // If a new photo was chosen but not yet saved, we need to 72228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // update the thumbnail to reflect this. 72328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus Bitmap bitmap = updatedBitmapForRawContact(rawContactId); 72428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus if (bitmap != null) editor.setPhotoBitmap(bitmap); 72528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 72672af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (editor instanceof RawContactEditorView) { 72772af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final RawContactEditorView rawContactEditor = (RawContactEditorView) editor; 7285ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov EditorListener listener = new EditorListener() { 729f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 730f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 731f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onRequest(int request) { 7322bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) { 73311bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov acquireAggregationSuggestions(rawContactEditor); 73411bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 735f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 736f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 737f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 7382293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor removedEditor) { 739f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 7405ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov }; 7415ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov 7425ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor(); 7435ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov if (mRequestFocus) { 7445ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.requestFocus(); 7455ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov mRequestFocus = false; 7465ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov } 7475ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.setEditorListener(listener); 748f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 7495ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView phoneticNameEditor = 7505ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov rawContactEditor.getPhoneticNameEditor(); 7515ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov phoneticNameEditor.setEditorListener(listener); 7527d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup); 7537d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 7549302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactId == mAggregationSuggestionsRawContactId) { 755f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov acquireAggregationSuggestions(rawContactEditor); 756f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 757f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 758cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 759f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 760eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = false; 761eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 762e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 763e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 764f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 765f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 766a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 767a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann // Refresh Action Bar as the visibility of the join command 768825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Activity can be null if we have been detached from the Activity 769825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann final Activity activity = getActivity(); 770825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (activity != null) activity.invalidateOptionsMenu(); 7716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 772eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 77328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus /** 77428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * If we've stashed a temporary file containing a contact's new photo, 77528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * decode it and return the bitmap. 77628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * @param rawContactId identifies the raw-contact whose Bitmap we'll try to return. 77728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus * @return Bitmap of photo for specified raw-contact, or null 77828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus */ 77928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus private Bitmap updatedBitmapForRawContact(long rawContactId) { 78028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus String path = mUpdatedPhotos.getString(String.valueOf(rawContactId)); 78128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus return BitmapFactory.decodeFile(path); 78228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus } 78328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 7846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type, 7856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro EntityDeltaList state) { 7866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final int mode; 7876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (type.areContactsWritable()) { 7886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (editor.hasSetPhoto()) { 7896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (hasMoreThanOnePhoto()) { 790ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.PHOTO_ALLOW_PRIMARY; 7916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 792ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.PHOTO_DISALLOW_PRIMARY; 7936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 7946fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 795ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.NO_PHOTO; 7966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 7976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 7986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (editor.hasSetPhoto() && hasMoreThanOnePhoto()) { 799ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus mode = PhotoActionPopup.Modes.READ_ONLY_ALLOW_PRIMARY; 8006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } else { 8016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Read-only and either no photo or the only photo ==> no options 802740552201d103b80bc49ea8a39a30536222672eaDaniel Lehmann editor.getPhotoEditor().setEditorListener(null); 8036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return; 8046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 8056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 8066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro mPhotoSelectionHandler = new PhotoHandler(mContext, editor, mode, state); 8076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro editor.getPhotoEditor().setEditorListener( 8086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro (PhotoHandler.PhotoEditorListener) mPhotoSelectionHandler.getListener()); 809cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 810cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 811e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private void bindGroupMetaData() { 812e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov if (mGroupMetaData == null) { 813e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov return; 814e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 815e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 816e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov int editorCount = mContent.getChildCount(); 817e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov for (int i = 0; i < editorCount; i++) { 81872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann BaseRawContactEditorView editor = (BaseRawContactEditorView) mContent.getChildAt(i); 819e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov editor.setGroupMetaData(mGroupMetaData); 820e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 821e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 822e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 8230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan private void saveDefaultAccountIfNecessary() { 8240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Verify that this is a newly created contact, that the contact is composed of only 8250353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // 1 raw contact, and that the contact is not a user profile. 8260353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (!Intent.ACTION_INSERT.equals(mAction) && mState.size() == 1 && 8270353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan !isEditingUserProfile()) { 8280353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 8290353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 8300353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 8310353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Find the associated account for this contact (retrieve it here because there are 8320353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // multiple paths to creating a contact and this ensures we always have the correct 8330353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // account). 8340353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan final EntityDelta entity = mState.get(0); 8350353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan final ValuesDelta values = entity.getValues(); 8360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan String name = values.getAsString(RawContacts.ACCOUNT_NAME); 8370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan String type = values.getAsString(RawContacts.ACCOUNT_TYPE); 8380353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan String dataSet = values.getAsString(RawContacts.DATA_SET); 8390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 8400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet account = (name == null || type == null) ? null : 8410353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan new AccountWithDataSet(name, type, dataSet); 8420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mEditorUtils.saveDefaultAndAllAccounts(account); 8430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 8440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 845d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void addAccountSwitcher( 846d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final EntityDelta currentState, BaseRawContactEditorView editor) { 847d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa ValuesDelta values = currentState.getValues(); 8482b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountWithDataSet currentAccount = new AccountWithDataSet( 849d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa values.getAsString(RawContacts.ACCOUNT_NAME), 8502b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.getAsString(RawContacts.ACCOUNT_TYPE), 8512b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.getAsString(RawContacts.DATA_SET)); 852d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final View accountView = editor.findViewById(R.id.account); 853fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan final View anchorView = editor.findViewById(R.id.account_container); 854d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa accountView.setOnClickListener(new View.OnClickListener() { 855d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 856d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onClick(View v) { 857d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final ListPopupWindow popup = new ListPopupWindow(mContext, null); 858a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa final AccountsListAdapter adapter = 8596f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki new AccountsListAdapter(mContext, 8606f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, currentAccount); 861d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setWidth(anchorView.getWidth()); 862d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAnchorView(anchorView); 863d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAdapter(adapter); 864d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setModal(true); 865d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 866d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setOnItemClickListener(new AdapterView.OnItemClickListener() { 867d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 868d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, 869d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa long id) { 870d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.dismiss(); 8712b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountWithDataSet newAccount = adapter.getItem(position); 872d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (!newAccount.equals(currentAccount)) { 873d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa rebindEditorsForNewContact(currentState, currentAccount, newAccount); 874d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 875d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 876d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 877d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.show(); 878d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 879d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 880d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 881d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 882a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan private void disableAccountSwitcher(BaseRawContactEditorView editor) { 883a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan // Remove the pressed state from the account header because the user cannot switch accounts 884a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan // on an existing contact 885a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan final View accountView = editor.findViewById(R.id.account); 886740552201d103b80bc49ea8a39a30536222672eaDaniel Lehmann accountView.setBackground(null); 887a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan accountView.setEnabled(false); 888a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan } 889a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan 890b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 891eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 892c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan inflater.inflate(R.menu.edit_contact, menu); 893cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 894cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 895b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 896eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onPrepareOptionsMenu(Menu menu) { 8979b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible 8989b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // because the custom action bar contains the "save" button now (not the overflow menu). 8999b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()? 900692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem doneMenu = menu.findItem(R.id.menu_done); 901692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem splitMenu = menu.findItem(R.id.menu_split); 902692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem joinMenu = menu.findItem(R.id.menu_join); 903692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu final MenuItem helpMenu = menu.findItem(R.id.menu_help); 904692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu 905692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // Set visibility of menus 906692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu doneMenu.setVisible(false); 9079b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 90803587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson // Split only if more than one raw profile and not a user profile 909692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu splitMenu.setVisible(mState != null && mState.size() > 1 && !isEditingUserProfile()); 91003587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 911692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // Cannot join a user profile 912692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu joinMenu.setVisible(!isEditingUserProfile()); 913692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu 914692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // help menu depending on whether this is inserting or editing 915692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu if (Intent.ACTION_INSERT.equals(mAction)) { 916692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // inserting 917692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu HelpUtils.prepareHelpMenuItem(getActivity(), helpMenu, R.string.help_url_people_add); 918692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } else if (Intent.ACTION_EDIT.equals(mAction)) { 919692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // editing 920692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu HelpUtils.prepareHelpMenuItem(getActivity(), helpMenu, R.string.help_url_people_edit); 921692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } else { 922692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu // something else, so don't show the help menu 923692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu helpMenu.setVisible(false); 924692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu } 92503587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 92602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int size = menu.size(); 92702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < size; i++) { 92802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov menu.getItem(i).setEnabled(mEnabled); 92902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 930cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 931cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 932b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 933cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public boolean onOptionsItemSelected(MenuItem item) { 934cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (item.getItemId()) { 935f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_done: 9369df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.CLOSE); 937f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_discard: 938d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return revert(); 939f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_split: 940f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSplitContactAction(); 941f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_join: 942f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doJoinContactAction(); 943f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 944f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 945f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 946cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 947f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSplitContactAction() { 948f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 949f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 950a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann final SplitContactConfirmationDialogFragment dialog = 9514a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann new SplitContactConfirmationDialogFragment(); 9524a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.setTargetFragment(this, 0); 9534a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG); 954f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 955f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 956f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 957f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doJoinContactAction() { 9584c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov if (!hasValidState()) { 9594c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov return false; 9604c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 9614c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 9624c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // If we just started creating a new contact and haven't added any data, it's too 9634c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // early to do a join 964764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) { 965a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(getActivity(), R.string.toast_join_with_empty_contact, 966a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.LENGTH_LONG).show(); 967a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov return true; 9684c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 9694c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 9709df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.JOIN); 971f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 972f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 973f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 974f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Check if our internal {@link #mState} is valid, usually checked before 975f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * performing user actions. 976f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 977f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean hasValidState() { 978f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return mState != null && mState.size() > 0; 979f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 980f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 981f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 982764637aba745612a9fdc07adb99c615263916fa8Josh Gargus * Return true if there are any edits to the current contact which need to 983764637aba745612a9fdc07adb99c615263916fa8Josh Gargus * be saved. 984764637aba745612a9fdc07adb99c615263916fa8Josh Gargus */ 985764637aba745612a9fdc07adb99c615263916fa8Josh Gargus private boolean hasPendingChanges() { 986764637aba745612a9fdc07adb99c615263916fa8Josh Gargus final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 987764637aba745612a9fdc07adb99c615263916fa8Josh Gargus return EntityModifier.hasChanges(mState, accountTypes); 988764637aba745612a9fdc07adb99c615263916fa8Josh Gargus } 989764637aba745612a9fdc07adb99c615263916fa8Josh Gargus 990764637aba745612a9fdc07adb99c615263916fa8Josh Gargus /** 991f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Saves or creates the contact based on the mode, and if successful 992f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * finishes the activity. 993f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 9949df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public boolean save(int saveMode) { 995a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 996f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 997f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 998f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 9998c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov // If we are about to close the editor - there is no need to refresh the data 1000a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.SPLIT) { 10019d2bcfb40d0ee107886eb99eba13a840e944ba43Dianne Hackborn getLoaderManager().destroyLoader(LOADER_DATA); 10028c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov } 10038c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov 1004825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.SAVING; 10056cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 1006764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (!hasPendingChanges()) { 1007ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann if (mLookupUri == null && saveMode == SaveMode.RELOAD) { 1008ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann // We don't have anything to save and there isn't even an existing contact yet. 1009ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann // Nothing to do, simply go back to editing mode 1010ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann mStatus = Status.EDITING; 1011ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann return true; 1012ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann } 101336d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, saveMode, mLookupUri != null, mLookupUri); 10146cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov return true; 10156cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov } 10166cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 1017a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov setEnabled(false); 1018f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 10190353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Store account as default account, only if this is a new contact 10200353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan saveDefaultAccountIfNecessary(); 10210353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan 10220353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Save contact 1023a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Intent intent = ContactSaveService.createSaveContactIntent(getActivity(), mState, 1024e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(), getActivity().getClass(), 1025e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus ContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos); 1026e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1027a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov getActivity().startService(intent); 1028f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 1029f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1030f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1031d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static class CancelEditDialogFragment extends DialogFragment { 1032d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1033d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static void show(ContactEditorFragment fragment) { 1034d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment dialog = new CancelEditDialogFragment(); 1035d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.setTargetFragment(fragment, 0); 1036d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.show(fragment.getFragmentManager(), "cancelEditor"); 1037d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1038d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1039d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 1040d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1041d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov AlertDialog dialog = new AlertDialog.Builder(getActivity()) 10424292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1043d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setMessage(R.string.cancel_confirmation_dialog_message) 10441ba8b6fea4c3f82ded19305874e72a326612aed1Katherine Kuan .setPositiveButton(android.R.string.ok, 1045d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov new DialogInterface.OnClickListener() { 1046d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 1047f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann public void onClick(DialogInterface dialogInterface, int whichButton) { 1048d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ((ContactEditorFragment)getTargetFragment()).doRevertAction(); 1049d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1050d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1051d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ) 1052d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setNegativeButton(android.R.string.cancel, null) 1053d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .create(); 1054d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return dialog; 1055d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1056d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1057d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1058d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private boolean revert() { 1059764637aba745612a9fdc07adb99c615263916fa8Josh Gargus if (mState == null || !hasPendingChanges()) { 1060d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov doRevertAction(); 1061d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } else { 1062d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment.show(this); 1063d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1064d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return true; 1065d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1066d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1067d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private void doRevertAction() { 1068825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // When this Fragment is closed we don't want it to auto-save 1069825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 107022fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onReverted(); 1071f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1072f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 10739b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan public void doSaveAction() { 10749b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan save(SaveMode.CLOSE); 10759b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan } 10769b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 10772b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov public void onJoinCompleted(Uri uri) { 107836d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri); 10792b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov } 10802b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov 108136d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, 108236d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro Uri contactLookupUri) { 1083a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Log.d(TAG, "onSaveCompleted(" + saveMode + ", " + contactLookupUri); 1084a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (hadChanges) { 108536d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded) { 1086a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode != SaveMode.JOIN) { 1087a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 1088a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1089a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else { 1090a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 1091a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1092a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1093f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 109415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.CLOSE: 10959df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov case SaveMode.HOME: 1096f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 109736d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 1098b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann final String requestAuthority = 1099b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri == null ? null : mLookupUri.getAuthority(); 1100f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1101f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String legacyAuthority = "contacts"; 1102f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1103f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = new Intent(); 11045649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan resultIntent.setAction(Intent.ACTION_VIEW); 1105f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (legacyAuthority.equals(requestAuthority)) { 1106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Build legacy Uri when requested by caller 1107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(Contacts.lookupContact( 1108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.getContentResolver(), contactLookupUri)); 1109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyContentUri = Uri.parse("content://contacts/people"); 1110f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyUri = ContentUris.withAppendedId( 1111f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann legacyContentUri, contactId); 1112f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(legacyUri); 1113f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Otherwise pass back a lookup-style Uri 1115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(contactLookupUri); 1116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1117f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1118f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1119f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 1120f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1121825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // It is already saved, so prevent that it is saved again 1122825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 11235649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan if (mListener != null) mListener.onSaveFinished(resultIntent); 1124f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1125a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 112615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.RELOAD: 1127dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov case SaveMode.JOIN: 112836d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro if (saveSucceeded && contactLookupUri != null) { 1129623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann // If it was a JOIN, we are now ready to bring up the join activity. 1130623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann if (saveMode == SaveMode.JOIN) { 1131623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann showJoinAggregateActivity(contactLookupUri); 1132623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann } 1133623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann 113415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If this was in INSERT, we are changing into an EDIT now. 113515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If it already was an EDIT, we are changing to the new Uri now 113615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann mState = null; 11371015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov load(Intent.ACTION_EDIT, contactLookupUri, null); 1138825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.LOADING; 113915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener); 114015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 114115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann break; 1142a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 114315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.SPLIT: 1144a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mStatus = Status.CLOSING; 1145a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann if (mListener != null) { 11468c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov mListener.onContactSplit(contactLookupUri); 1147a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } else { 1148a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann Log.d(TAG, "No listener registered, can not call onSplitFinished"); 1149a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1150f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1151f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1152f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1153f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1154f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1155f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 1156f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 1157f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 1158f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1159f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 116073a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov if (contactLookupUri == null || !isAdded()) { 1161f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 1162f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1163f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1164f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 1165623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = isContactWritable(); 1166f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = new Intent(JoinContactActivity.JOIN_CONTACT); 1167f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(JoinContactActivity.EXTRA_TARGET_CONTACT_ID, mContactIdForJoin); 1168a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_JOIN); 1169f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1170f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1171f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1172f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 1173f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1174f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 11752b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin, 1176623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann contactId, mContactWritableForJoin, 11772b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED); 11782b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov mContext.startService(intent); 1179f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1180f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1181f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1182ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov * Returns true if there is at least one writable raw contact in the current contact. 1183ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov */ 1184ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov private boolean isContactWritable() { 1185a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1186ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov int size = mState.size(); 1187ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov for (int i = 0; i < size; i++) { 1188ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov ValuesDelta values = mState.get(i).getValues(); 1189ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 11902b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = values.getAsString(RawContacts.DATA_SET); 11912b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type = accountTypes.getAccountType(accountType, dataSet); 119296e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (type.areContactsWritable()) { 1193ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return true; 1194ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1195ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1196ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return false; 1197ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1198ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov 11992bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson private boolean isEditingUserProfile() { 12002bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson return mNewLocalProfile || mIsUserProfile; 12012bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson } 12022bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson 1203cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public static interface Listener { 1204cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 120522fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was not found, so somehow close this fragment. This is raised after a contact 120622fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * is removed via Menu/Delete (unless it was a new contact) 1207cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 120822fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onContactNotFound(); 1209f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1210f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 12118c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov * Contact was split, so we can close now. 1212a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * @param newLookupUri The lookup uri of the new contact that should be shown to the user. 1213a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * The editor tries best to chose the most natural contact here. 1214f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 12158c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov void onContactSplit(Uri newLookupUri); 1216f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1217f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1218f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User has tapped Revert, close the fragment now. 1219f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 122022fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onReverted(); 1221f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1222f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 122322fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was saved and the Fragment can now be closed safely. 1224f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 12255649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan void onSaveFinished(Intent resultIntent); 1226b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann 1227b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann /** 1228e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * User switched to editing a different contact (a suggestion from the 1229e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * aggregation engine). 1230e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov */ 1231e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov void onEditOtherContactRequested( 1232e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov Uri contactLookupUri, ArrayList<ContentValues> contentValues); 1233fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1234fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1235fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * Contact is being created for an external account that provides its own 1236fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * new contact activity. 1237fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 12382b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro void onCustomCreateContactActivityRequested(AccountWithDataSet account, 12392b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro Bundle intentExtras); 1240fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1241fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1242fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * The edited raw contact belongs to an external account that provides 1243fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * its own edit activity. 1244fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * 1245fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * @param redirect indicates that the current editor should be closed 1246fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * before the custom editor is shown. 1247fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 12482b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro void onCustomEditContactActivityRequested(AccountWithDataSet account, Uri rawContactUri, 1249fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Bundle intentExtras, boolean redirect); 1250f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1251f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1252f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private class EntityDeltaComparator implements Comparator<EntityDelta> { 1253f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1254f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Compare EntityDeltas for sorting the stack of editors. 1255f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 12564a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann @Override 1257f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public int compare(EntityDelta one, EntityDelta two) { 1258f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check direct equality 1259f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (one.equals(two)) { 1260f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 0; 1261f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1262f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1263a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 12642b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountType1 = one.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 12652b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet1 = one.getValues().getAsString(RawContacts.DATA_SET); 12662b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type1 = accountTypes.getAccountType(accountType1, dataSet1); 12672b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountType2 = two.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 12682b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet2 = two.getValues().getAsString(RawContacts.DATA_SET); 12692b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type2 = accountTypes.getAccountType(accountType2, dataSet2); 1270f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1271f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check read-only 127296e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann if (!type1.areContactsWritable() && type2.areContactsWritable()) { 1273f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 127496e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann } else if (type1.areContactsWritable() && !type2.areContactsWritable()) { 1275f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1276f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1277f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1278f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account type 1279f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean skipAccountTypeCheck = false; 1280b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount1 = type1 instanceof GoogleAccountType; 1281b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount2 = type2 instanceof GoogleAccountType; 128269f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (isGoogleAccount1 && !isGoogleAccount2) { 1283f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 128469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (!isGoogleAccount1 && isGoogleAccount2) { 1285f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 128669f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (isGoogleAccount1 && isGoogleAccount2){ 1287f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann skipAccountTypeCheck = true; 1288f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1289f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1290f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int value; 1291f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!skipAccountTypeCheck) { 1292b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (type1.accountType == null) { 12932776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru return 1; 12942776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru } 1295b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov value = type1.accountType.compareTo(type2.accountType); 1296f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1297f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 12982b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else { 12992b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro // Fall back to data set. 13002b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (type1.dataSet != null) { 13012b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro value = type1.dataSet.compareTo(type2.dataSet); 13022b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (value != 0) { 13032b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return value; 13042b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 13052b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else if (type2.dataSet != null) { 13062b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return 1; 13072b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 1308f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1309f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1310f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1311f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account name 1312f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta oneValues = one.getValues(); 1313f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String oneAccount = oneValues.getAsString(RawContacts.ACCOUNT_NAME); 1314f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneAccount == null) oneAccount = ""; 1315f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta twoValues = two.getValues(); 1316f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String twoAccount = twoValues.getAsString(RawContacts.ACCOUNT_NAME); 1317f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (twoAccount == null) twoAccount = ""; 1318f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann value = oneAccount.compareTo(twoAccount); 1319f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1320f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 1321f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1322f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1323f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Both are in the same account, fall back to contact ID 1324f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long oneId = oneValues.getAsLong(RawContacts._ID); 1325f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long twoId = twoValues.getAsLong(RawContacts._ID); 1326f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneId == null) { 1327f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1328f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoId == null) { 1329f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1330f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1331f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1332f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return (int)(oneId - twoId); 1333f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1334f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1335f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1336f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1337f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Returns the contact ID for the currently edited contact or 0 if the contact is new. 1338f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1339f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected long getContactId() { 1340c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov if (mState != null) { 1341c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov for (EntityDelta rawContact : mState) { 1342c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID); 1343c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov if (contactId != null) { 1344c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov return contactId; 1345c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov } 1346f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1347f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1348f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return 0; 1349f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1350f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1351f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1352f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Triggers an asynchronous search for aggregation suggestions. 1353f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 135472af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann public void acquireAggregationSuggestions(RawContactEditorView rawContactEditor) { 13559302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov long rawContactId = rawContactEditor.getRawContactId(); 13569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (mAggregationSuggestionsRawContactId != rawContactId 13579302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov && mAggregationSuggestionView != null) { 13589302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 13599302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = null; 13609302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionEngine.reset(); 13619302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 13629302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 13639302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = rawContactId; 13649302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 1365f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine == null) { 1366f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine = new AggregationSuggestionEngine(getActivity()); 1367f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.setListener(this); 1368f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.start(); 1369f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1370f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1371916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mAggregationSuggestionEngine.setContactId(getContactId()); 1372916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 1373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann LabeledEditorView nameEditor = rawContactEditor.getNameEditor(); 1374f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.onNameChange(nameEditor.getValues()); 1375f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1376f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1377f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 1378f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onAggregationSuggestionChange() { 1379a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!isAdded() || mState == null || mStatus != Status.EDITING) { 138002cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov return; 138102cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov } 138202cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov 13836c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionPopup != null && mAggregationSuggestionPopup.isShowing()) { 13846c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.dismiss(); 13859302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1386f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 13876c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) { 1388f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 1389f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1390f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 13916c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final RawContactEditorView rawContactView = 13926c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId); 139302a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki if (rawContactView == null) { 139402a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki return; // Raw contact deleted? 139502a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki } 13966c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final View anchorView = rawContactView.findViewById(R.id.anchor_view); 13976c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = new ListPopupWindow(mContext, null); 13986c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAnchorView(anchorView); 13996c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setWidth(anchorView.getWidth()); 14006c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 14016c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAdapter( 14026c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new AggregationSuggestionAdapter(getActivity(), 14036c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mState.size() == 1 && mState.get(0).isContactInsert(), 14046c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa this, mAggregationSuggestionEngine.getSuggestions())); 14056c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setOnItemClickListener(mAggregationSuggestionItemClickListener); 14066c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.show(); 1407bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1408bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1409bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1410bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onJoinAction(long contactId, List<Long> rawContactIdList) { 1411bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = new long[rawContactIdList.size()]; 1412bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov for (int i = 0; i < rawContactIds.length; i++) { 1413bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov rawContactIds[i] = rawContactIdList.get(i); 1414bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1415bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov JoinSuggestedContactDialogFragment dialog = 1416bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new JoinSuggestedContactDialogFragment(); 1417bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1418bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putLongArray("rawContactIds", rawContactIds); 1419bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1420bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 142174f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov try { 142274f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov dialog.show(getFragmentManager(), "join"); 142374f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } catch (Exception ex) { 142474f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov // No problem - the activity is no longer available to display the dialog 142574f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } 1426bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1427bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1428bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class JoinSuggestedContactDialogFragment extends DialogFragment { 1429bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1430bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1431bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1432bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 14334292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1434bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_join_dialog_message) 1435bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1436bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1437f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 1438bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1439bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1440bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1441bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = 1442bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getLongArray("rawContactIds"); 1443bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doJoinSuggestedContact(rawContactIds); 1444bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1445bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1446bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1447bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1448bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1449bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1450bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1451bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1452bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1453bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Joins the suggested contact (specified by the id's of constituent raw 1454bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * contacts), save all changes, and stay in the editor. 1455bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1456bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doJoinSuggestedContact(long[] rawContactIds) { 1457cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1458cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov return; 1459cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov } 1460cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov 1461bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mState.setJoinWithRawContacts(rawContactIds); 14629df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 1463bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1464bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1465bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1466bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onEditAction(Uri contactLookupUri) { 1467bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov SuggestionEditConfirmationDialogFragment dialog = 1468bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new SuggestionEditConfirmationDialogFragment(); 1469bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1470bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putParcelable("contactUri", contactLookupUri); 1471bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1472bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 1473bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.show(getFragmentManager(), "edit"); 1474bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1475bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1476bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class SuggestionEditConfirmationDialogFragment extends DialogFragment { 1477bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1478bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1479bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1480bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 14814292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1482bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_edit_dialog_message) 1483bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1484bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1485f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 1486bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1487bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1488bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1489bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Uri contactUri = 1490bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getParcelable("contactUri"); 1491bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doEditSuggestedContact(contactUri); 1492bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1493bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1494bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1495bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1496bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1497bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1498bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1499bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1500bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1501bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Abandons the currently edited contact and switches to editing the suggested 1502bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * one, transferring all the data there 1503bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1504bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doEditSuggestedContact(Uri contactUri) { 1505bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov if (mListener != null) { 1506a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann // make sure we don't save this contact when closing down 1507a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann mStatus = Status.CLOSING; 1508bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mListener.onEditOtherContactRequested( 1509bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov contactUri, mState.get(0).getContentValues()); 1510bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1511bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1512bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1513a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov public void setAggregationSuggestionViewEnabled(boolean enabled) { 1514a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (mAggregationSuggestionView == null) { 1515a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov return; 1516a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1517a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1518a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 1519a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov R.id.aggregation_suggestions); 1520a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov int count = itemList.getChildCount(); 1521a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov for (int i = 0; i < count; i++) { 1522a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov itemList.getChildAt(i).setEnabled(enabled); 1523a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1524a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1525a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1526f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1527f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 1528b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann outState.putParcelable(KEY_URI, mLookupUri); 1529d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putString(KEY_ACTION, mAction); 1530d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 1531f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (hasValidState()) { 1532f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Store entities with modifications 1533f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_EDIT_STATE, mState); 1534f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1535f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1536f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 1537f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator); 1538f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mCurrentPhotoFile != null) { 1539f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putString(KEY_CURRENT_PHOTO_FILE, mCurrentPhotoFile.toString()); 1540f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1541f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 1542623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin); 15439302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov outState.putLong(KEY_SHOW_JOIN_SUGGESTIONS, mAggregationSuggestionsRawContactId); 154402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov outState.putBoolean(KEY_ENABLED, mEnabled); 1545ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile); 1546ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile); 1547ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov outState.putInt(KEY_STATUS, mStatus); 154828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos); 154928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 1550f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 1551f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1552f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1553d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 1554f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 1555f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (mStatus == Status.SUB_ACTIVITY) { 1556f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.EDITING; 1557f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov } 1558f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 15596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // See if the photo selection handler handles this result. 15606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (mPhotoSelectionHandler != null && mPhotoSelectionHandler.handlePhotoActivityResult( 15616fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro requestCode, resultCode, data)) { 15626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return; 15636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1564f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 15656fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro switch (requestCode) { 1566a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_JOIN: { 15670353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Ignore failed requests 15680353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) return; 1569f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 1570f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 1571f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 1572f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 15734a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann break; 1574f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 15750353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan case REQUEST_CODE_ACCOUNTS_CHANGED: { 15760353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // Bail if the account selector was not successful. 15770353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (resultCode != Activity.RESULT_OK) { 15780353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan mListener.onReverted(); 15790353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 15800353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 15810353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there's an account specified, use it. 15820353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (data != null) { 15830353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan AccountWithDataSet account = data.getParcelableExtra(Intents.Insert.ACCOUNT); 15840353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan if (account != null) { 15850353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(account); 15860353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan return; 15870353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 15880353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 15890353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // If there isn't an account specified, then this is likely a phone-local 15900353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // contact, so we should continue setting up the editor by automatically selecting 15910353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan // the most appropriate account. 15920353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan createContact(); 15930353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan break; 15940353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan } 1595f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1596cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 15979cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 1598c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann /** 1599c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann * Sets the photo stored in mPhoto and writes it to the RawContact with the given id 1600c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann */ 1601e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus private void setPhoto(long rawContact, Bitmap photo, File photoFile) { 1602bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact); 1603e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1604e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus if (photo == null || photo.getHeight() < 0 || photo.getWidth() < 0) { 1605e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus // This is unexpected. 1606e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus Log.w(TAG, "Invalid bitmap passed to setPhoto()"); 1607e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus } 1608e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 16099302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestingEditor != null) { 16109302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov requestingEditor.setPhotoBitmap(photo); 16119302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } else { 16129302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Log.w(TAG, "The contact that requested the photo is no longer present."); 16139302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1614e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus 1615e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus mUpdatedPhotos.putString(String.valueOf(rawContact), photoFile.getAbsolutePath()); 16169302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 16179302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 16189302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov /** 16199302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov * Finds raw contact editor view for the given rawContactId. 16209302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov */ 1621bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public BaseRawContactEditorView getRawContactEditorView(long rawContactId) { 1622c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 1623c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann final View childView = mContent.getChildAt(i); 162472af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 162572af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 16269302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (editor.getRawContactId() == rawContactId) { 16279302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return editor; 1628c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1629c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1630c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 16319302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return null; 1632c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1633c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1634fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 1635fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann * Returns true if there is currently more than one photo on screen. 1636fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1637fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann private boolean hasMoreThanOnePhoto() { 1638fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int count = mContent.getChildCount(); 1639fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int countWithPicture = 0; 1640fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann for (int i = 0; i < count; i++) { 1641fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann final View childView = mContent.getChildAt(i); 1642fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (childView instanceof BaseRawContactEditorView) { 1643fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 1644fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (editor.hasSetPhoto()) { 1645fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann countWithPicture++; 1646fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (countWithPicture > 1) return true; 1647fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1648fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1649fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1650fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 1651fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann return false; 16529cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1653222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1654222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann /** 1655222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann * The listener for the data loader 1656222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann */ 1657222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener = 1658222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann new LoaderCallbacks<ContactLoader.Result>() { 1659222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1660222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) { 1661222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann mLoaderStartTime = SystemClock.elapsedRealtime(); 1662b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann return new ContactLoader(mContext, mLookupUri); 1663222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1664222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1665222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1666222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) { 1667222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long loaderCurrentTime = SystemClock.elapsedRealtime(); 1668222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime)); 16692621c5bb7049401c8bce740005fa60bf1b304b86Makoto Onuki if (!data.isLoaded()) { 1670222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann // Item has been deleted 1671222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.i(TAG, "No contact found. Closing activity"); 167222fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onContactNotFound(); 1673222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return; 1674222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1675222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1676825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.EDITING; 16776caccaeeed943db323be89853a108f422e670760Dmitri Plotnikov mLookupUri = data.getLookupUri(); 1678222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataStartTime = SystemClock.elapsedRealtime(); 1679222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann setData(data); 1680222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataEndTime = SystemClock.elapsedRealtime(); 1681c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1682222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime)); 1683222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 16844ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1685623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann @Override 16864ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<ContactLoader.Result> loader) { 16874ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1688222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann }; 1689a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 1690e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov /** 1691be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan * The listener for the group meta data loader for all groups. 1692e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov */ 1693e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener = 1694e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov new LoaderCallbacks<Cursor>() { 1695e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1696e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1697e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public CursorLoader onCreateLoader(int id, Bundle args) { 1698be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI); 1699e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1700e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1701e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1702e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1703e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov mGroupMetaData = data; 1704e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 1705e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 17064ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1707f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann @Override 17084ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 17094ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1710e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov }; 1711e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1712a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann @Override 1713a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann public void onSplitContactConfirmed() { 1714b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa if (mState == null) { 1715b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // This may happen when this Fragment is recreated by the system during users 1716b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // confirming the split action (and thus this method is called just before onCreate()), 1717b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa // for example. 1718b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa Log.e(TAG, "mState became null during the user's confirming split action. " + 1719b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa "Cannot perform the save action."); 1720b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa return; 1721b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa } 1722b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa 1723a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann mState.markRawContactsForSplitting(); 17249df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.SPLIT); 1725a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1726a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 17286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * Custom photo handler for the editor. The inner listener that this creates also has a 17296fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * reference to the editor and acts as an {@link EditorListener}, and uses that editor to hold 17306fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * state information in several of the listener methods. 17316fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 17326fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoHandler extends PhotoSelectionHandler { 173328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 173428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus final long mRawContactId; 1735e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus private final BaseRawContactEditorView mEditor; 17369a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann private PhotoActionListener mPhotoEditorListener; 173728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 17386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode, 17396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro EntityDeltaList state) { 17406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro super(context, editor.getPhotoEditor(), photoMode, false, state); 1741e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mEditor = editor; 174228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mRawContactId = editor.getRawContactId(); 17439a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann mPhotoEditorListener = new PhotoEditorListener(); 1744e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1745e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1746e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1747e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus public PhotoActionListener getListener() { 17489a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann return mPhotoEditorListener; 1749e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus } 1750e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus 1751e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus @Override 1752e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus public void startPhotoActivity(Intent intent, int requestCode, File photoFile) { 1753e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 1754e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mStatus = Status.SUB_ACTIVITY; 1755e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus mCurrentPhotoFile = photoFile; 1756e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus ContactEditorFragment.this.startActivityForResult(intent, requestCode); 17579442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17589442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 17596fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener 17606fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro implements EditorListener { 1761fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 17626fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 17636fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRequest(int request) { 17646fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (!hasValidState()) return; 1765a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17666fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (request == EditorListener.REQUEST_PICK_PHOTO) { 17676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro onClick(mEditor.getPhotoEditor()); 17689442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17699442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1770a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 17726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onDeleteRequested(Editor removedEditor) { 17736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // The picture cannot be deleted, it can only be removed, which is handled by 17746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // onRemovePictureChosen() 17756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 1776a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17776fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 17786fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to set the selected photo as the (super) primary photo 17796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 17806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 17816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onUseAsPrimaryChosen() { 17826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Set the IsSuperPrimary for each editor 17836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro int count = mContent.getChildCount(); 17846fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro for (int i = 0; i < count; i++) { 17856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final View childView = mContent.getChildAt(i); 17866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro if (childView instanceof BaseRawContactEditorView) { 17876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final BaseRawContactEditorView editor = 17886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro (BaseRawContactEditorView) childView; 17896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro final PhotoEditorView photoEditor = editor.getPhotoEditor(); 17906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro photoEditor.setSuperPrimary(editor == mEditor); 17916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 17926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 17936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 17949442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 17956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro /** 17966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro * User has chosen to remove a picture 17976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro */ 17986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 17996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onRemovePictureChosen() { 18006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro mEditor.setPhotoBitmap(null); 180128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus 180228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // Prevent bitmap from being restored if rotate the device. 180328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus // (only if we first chose a new photo before removing it) 180428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus mUpdatedPhotos.remove(String.valueOf(mRawContactId)); 18056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 18066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 18076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 18086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onPhotoSelected(Bitmap bitmap) { 1809e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus setPhoto(mRawContactIdRequestingPhoto, bitmap, mCurrentPhotoFile); 18106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro mRawContactIdRequestingPhoto = -1; 18116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 18126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 18136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 18146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public File getCurrentPhotoFile() { 18156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro return mCurrentPhotoFile; 18166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro } 18176fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro 18186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro @Override 18196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro public void onPhotoSelectionDismissed() { 18206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro // Nothing to do. 18219442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 18224a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 18234a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 18242ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1825