ContactEditorFragment.java revision 2245870a1354df03512010e4968b144840894fb7
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; 232b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikovimport com.android.contacts.activities.ContactEditorActivity; 24d21ddb2c96e71f43eaf7addc25e163181d1ca87dDmitri Plotnikovimport com.android.contacts.activities.JoinContactActivity; 2518ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; 2618ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.Editor.EditorListener; 274597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType; 28a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikovimport com.android.contacts.model.AccountTypeManager; 292b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoroimport com.android.contacts.model.AccountWithDataSet; 30f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityDelta; 31f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityDelta.ValuesDelta; 32ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmannimport com.android.contacts.model.EntityDeltaList; 33f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityModifier; 3435769b804fbfd5a1fc0b2c36cd0a786d662c4334Daniel Lehmannimport com.android.contacts.model.GoogleAccountType; 35d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.util.AccountsListAdapter; 36f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 37f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.accounts.Account; 38cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity; 39bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.AlertDialog; 40bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.Dialog; 41bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.DialogFragment; 42222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.Fragment; 43222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager; 44222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 45cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ActivityNotFoundException; 46cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 47cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentValues; 48cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 49e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikovimport android.content.CursorLoader; 50bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface; 51e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikovimport android.content.Entity; 52cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 53cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader; 54f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor; 55f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 56f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.graphics.Rect; 57f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.media.MediaScannerConnection; 58cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 59cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 60f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.os.Environment; 619767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock; 62cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 63362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Event; 64362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Organization; 65cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 66362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 67f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 680a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoroimport android.provider.ContactsContract.DisplayPhoto; 69be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuanimport android.provider.ContactsContract.Groups; 702013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmannimport android.provider.ContactsContract.Intents; 71f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 72f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.MediaStore; 73cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 74cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 75cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu; 76cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater; 77cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem; 78cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 79cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 80d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.AdapterView; 816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener; 826c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.BaseAdapter; 8380d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 84d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.ListPopupWindow; 85cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast; 86cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 87f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.io.File; 88f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.text.SimpleDateFormat; 89cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport java.util.ArrayList; 90f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections; 91f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Comparator; 92f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Date; 93f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List; 94f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 95a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmannpublic class ContactEditorFragment extends Fragment implements 96d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa SplitContactConfirmationDialogFragment.Listener, 97fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener, 98fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ExternalRawContactEditorView.Listener { 99cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 1002245870a1354df03512010e4968b144840894fb7Frank Sposaro private static final String TAG = ContactEditorFragment.class.getSimpleName(); 101cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 102f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int LOADER_DATA = 1; 103e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private static final int LOADER_GROUPS = 2; 104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 105d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_URI = "uri"; 106d364314c460152db7089b304beec81b3675893baDmitri Plotnikov private static final String KEY_ACTION = "action"; 107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_EDIT_STATE = "state"; 108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester"; 109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator"; 110f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CURRENT_PHOTO_FILE = "currentphotofile"; 111f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin"; 112623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin"; 1139302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions"; 11402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private static final String KEY_ENABLED = "enabled"; 115ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov private static final String KEY_STATUS = "status"; 116ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile"; 117ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private static final String KEY_IS_USER_PROFILE = "isUserProfile"; 118f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 119a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public static final String SAVE_MODE_EXTRA_KEY = "saveMode"; 120a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 12115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 1227d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * An intent extra that forces the editor to add the edited contact 1237d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * to the default group (e.g. "My Contacts"). 1247d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov */ 1257d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory"; 1267d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 127ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile"; 128ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 1297d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov /** 13015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Modes that specify what the AsyncTask has to perform after saving 13115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 132c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // TODO: Move this into a common utils class or the save service because the contact and 133c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan // group editors need to use this interface definition 1349df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public interface SaveMode { 13515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 13615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Close the editor after saving 13715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 13815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int CLOSE = 0; 13915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 14015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 14115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Reload the data so that the user can continue editing 14215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int RELOAD = 1; 14415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 14515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 14615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Split the contact after saving 14715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int SPLIT = 2; 14915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 15015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 15115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Join another contact after saving 15215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 15315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int JOIN = 3; 1549df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov 1559df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov /** 1569df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov * Navigate to Contacts Home activity after saving. 1579df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov */ 1589df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public static final int HOME = 4; 15915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 160a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 161825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private interface Status { 162825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 163825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * The loader is fetching data 164825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 165825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int LOADING = 0; 166825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 167825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 168825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * Not currently busy. We are waiting for the user to enter data 169825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 170825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int EDITING = 1; 171825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 172825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 173f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * The data is currently being saved. This is used to prevent more 174f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * auto-saves (they shouldn't overlap) 175825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 176825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int SAVING = 2; 177825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 178825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 179a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * Prevents any more saves. This is used if in the following cases: 180a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After Save/Close 181a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After Revert 182a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann * - After the user has accepted an edit suggestion 183825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 184825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int CLOSING = 3; 185f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 186f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov /** 187f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * Prevents saving while running a child activity. 188f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov */ 189f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov public static final int SUB_ACTIVITY = 4; 190825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 191825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 192a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_JOIN = 0; 193a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_CAMERA_WITH_DATA = 1; 194a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_PHOTO_PICKED_WITH_DATA = 2; 195f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 196c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann private Bitmap mPhoto = null; 197f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mRawContactIdRequestingPhoto = -1; 198c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann private long mRawContactIdRequestingPhotoAfterLoad = -1; 199cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 200f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private final EntityDeltaComparator mComparator = new EntityDeltaComparator(); 201f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final File PHOTO_DIR = new File( 203f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Environment.getExternalStorageDirectory() + "/DCIM/Camera"); 204f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 205e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private Cursor mGroupMetaData; 206e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 207f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private File mCurrentPhotoFile; 208cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 2090a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro // Height/width (in pixels) to request for the photo - queried from the provider. 2100a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro private int mPhotoPickSize; 2110a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro 212cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Context mContext; 213f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mAction; 214b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann private Uri mLookupUri; 215f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Bundle mIntentExtras; 216cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Listener mListener; 217cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 218f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mContactIdForJoin; 219623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann private boolean mContactWritableForJoin; 220cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 221f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private LinearLayout mContent; 222ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann private EntityDeltaList mState; 223cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 224f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 225cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 2269767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann private long mLoaderStartTime; 2279767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann 228825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private int mStatus; 229825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 230f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private AggregationSuggestionEngine mAggregationSuggestionEngine; 2319302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private long mAggregationSuggestionsRawContactId; 2329302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private View mAggregationSuggestionView; 233f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 2346c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private ListPopupWindow mAggregationSuggestionPopup; 2356c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2366c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private static final class AggregationSuggestionAdapter extends BaseAdapter { 2376c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final Activity mActivity; 2386c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final boolean mSetNewContact; 2396c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final AggregationSuggestionView.Listener mListener; 2406c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private final List<Suggestion> mSuggestions; 2416c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2426c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public AggregationSuggestionAdapter(Activity activity, boolean setNewContact, 2436c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) { 2446c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mActivity = activity; 2456c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSetNewContact = setNewContact; 2466c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mListener = listener; 2476c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mSuggestions = suggestions; 2486c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2496c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2506c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2516c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public View getView(int position, View convertView, ViewGroup parent) { 2526c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa Suggestion suggestion = (Suggestion) getItem(position); 2536c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa LayoutInflater inflater = mActivity.getLayoutInflater(); 2546c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa AggregationSuggestionView suggestionView = 2556c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (AggregationSuggestionView) inflater.inflate( 2566c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa R.layout.aggregation_suggestions_item, null); 2576c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setNewContact(mSetNewContact); 2586c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.setListener(mListener); 2596c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.bindSuggestion(suggestion); 2606c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return suggestionView; 2616c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2626c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2636c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2646c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public long getItemId(int position) { 2656c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return position; 2666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2676c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2686c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2696c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public Object getItem(int position) { 2706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.get(position); 2716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2726c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2736c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2746c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public int getCount() { 2756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa return mSuggestions.size(); 2766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa private OnItemClickListener mAggregationSuggestionItemClickListener = 2806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new OnItemClickListener() { 2816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa @Override 2826c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 2836c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view; 2846c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa suggestionView.handleItemClickEvent(); 2856c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.dismiss(); 2866c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = null; 2876c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa } 2886c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa }; 2896c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa 2907d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov private boolean mAutoAddToDefaultGroup; 2917d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 29202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private boolean mEnabled = true; 293eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov private boolean mRequestFocus; 294ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private boolean mNewLocalProfile = false; 295ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson private boolean mIsUserProfile = false; 29602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 297cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 298cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 299cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 30002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public void setEnabled(boolean enabled) { 30102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mEnabled != enabled) { 30202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = enabled; 30302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mContent != null) { 30402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int count = mContent.getChildCount(); 30502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < count; i++) { 30602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mContent.getChildAt(i).setEnabled(enabled); 30702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 30802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 309a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov setAggregationSuggestionViewEnabled(enabled); 31002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov final Activity activity = getActivity(); 31102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (activity != null) activity.invalidateOptionsMenu(); 31202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 31302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 31402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 315cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 316cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public void onAttach(Activity activity) { 317cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann super.onAttach(activity); 318cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann mContext = activity; 3190a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro loadPhotoPickSize(); 320cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 321cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 322cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 323f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onStop() { 324f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super.onStop(); 325f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine != null) { 326f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.quit(); 327f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 328248fba273e867616b1f8973dac6ce3e5ee1ba544Dmitri Plotnikov 329825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If anything was left unsaved, save it now but keep the editor open. 330f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) { 331623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann save(SaveMode.RELOAD); 332825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 333f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 334f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 335f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 336cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 337cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 338cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 339f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 340e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 3413648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 342cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 343825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If we are in an orientation change, we already have mState (it was loaded by onCreate) 344825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (mState != null) { 345825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann bindEditors(); 346825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 347825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 348cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 349cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 350cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 351222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 352222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onActivityCreated(Bundle savedInstanceState) { 353222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann super.onActivityCreated(savedInstanceState); 354222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 355825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann Log.d(TAG, "onActivityCreated(" + savedInstanceState + ")"); 356222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 357825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Handle initial actions only when existing state missing 3584a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann final boolean hasIncomingState = savedInstanceState != null; 359825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 360825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (!hasIncomingState) { 361825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (Intent.ACTION_EDIT.equals(mAction)) { 362825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener); 363825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } else if (Intent.ACTION_INSERT.equals(mAction)) { 3642013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann final Account account = mIntentExtras == null ? null : 3652b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT); 3662b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = mIntentExtras == null ? null : 3672b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mIntentExtras.getString(Intents.Insert.DATA_SET); 3682013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann 3692013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann if (account != null) { 3702013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // Account specified in Intent 3712b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro createContact(new AccountWithDataSet(account.name, account.type, dataSet)); 3722013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } else { 3732013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // No Account specified. Let the user choose 37440bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov // Load Accounts async so that we can present them 375d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa createContact(); 3762013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } 377a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else if (ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(mAction)) { 378a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov // do nothing 379825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } else throw new IllegalArgumentException("Unknown Action String " + mAction + 380825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT); 381825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 382222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 383222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 384e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 385e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onStart() { 386e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener); 387e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov super.onStart(); 388e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 389e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 3901015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov public void load(String action, Uri lookupUri, Bundle intentExtras) { 391f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mAction = action; 392b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = lookupUri; 393f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mIntentExtras = intentExtras; 3947d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov mAutoAddToDefaultGroup = mIntentExtras != null 3957d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY); 396ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = mIntentExtras != null 397ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson && mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE); 398f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 399f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 400f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void setListener(Listener value) { 401f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener = value; 402cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 403cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 404cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 405f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 406d364314c460152db7089b304beec81b3675893baDmitri Plotnikov if (savedState != null) { 407d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // Restore mUri before calling super.onCreate so that onInitializeLoaders 408d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // would already have a uri and an action to work with 409b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = savedState.getParcelable(KEY_URI); 410d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mAction = savedState.getString(KEY_ACTION); 411d364314c460152db7089b304beec81b3675893baDmitri Plotnikov } 412d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 413f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 414f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 415f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (savedState == null) { 416f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If savedState is non-null, onRestoreInstanceState() will restore the generator. 417f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = new ViewIdGenerator(); 418f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 419825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Read state from savedState. No loading involved here 420ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = savedState.<EntityDeltaList> getParcelable(KEY_EDIT_STATE); 421f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactIdRequestingPhoto = savedState.getLong( 422f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 423f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR); 424f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String fileName = savedState.getString(KEY_CURRENT_PHOTO_FILE); 425f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (fileName != null) { 426f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mCurrentPhotoFile = new File(fileName); 427cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 428f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 429623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN); 4309302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = savedState.getLong(KEY_SHOW_JOIN_SUGGESTIONS); 43102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = savedState.getBoolean(KEY_ENABLED); 432ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov mStatus = savedState.getInt(KEY_STATUS); 433ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE); 434ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE); 435cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 436cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 437cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 438bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann public void setData(ContactLoader.Result data) { 439d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann // If we have already loaded data, we do not want to change it here to not confuse the user 440d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann if (mState != null) { 441d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann Log.v(TAG, "Ignoring background change. This will have to be rebased later"); 442d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann return; 443d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann } 444d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann 445fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov // See if this edit operation needs to be redirected to a custom editor 446fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ArrayList<Entity> entities = data.getEntities(); 447fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (entities.size() == 1) { 448fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Entity entity = entities.get(0); 449fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentValues entityValues = entity.getEntityValues(); 450fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE); 4512b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet = entityValues.getAsString(RawContacts.DATA_SET); 4522b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType( 4532b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro type, dataSet); 454fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (accountType.getEditContactActivityClassName() != null) { 455fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 456fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov String name = entityValues.getAsString(RawContacts.ACCOUNT_NAME); 457fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID); 4582b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro mListener.onCustomEditContactActivityRequested( 4592b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro new AccountWithDataSet(name, type, dataSet), 460fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 461fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mIntentExtras, true); 462fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 463fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov return; 464fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 465fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 466fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 467fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov bindEditorsForExistingContact(data); 468fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 469fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 470fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov @Override 4712b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro public void onExternalEditorRequest(AccountWithDataSet account, Uri uri) { 472fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(account, uri, null, false); 473fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 474fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 475fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov private void bindEditorsForExistingContact(ContactLoader.Result data) { 47602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov setEnabled(true); 47702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 478a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mState = EntityDeltaList.fromIterator(data.getEntities().iterator()); 4791ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov setIntentExtras(mIntentExtras); 4801ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov mIntentExtras = null; 481e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikov 482ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // For user profile, change the contacts query URI 483ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson mIsUserProfile = data.isUserProfile(); 484ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mIsUserProfile) { 485ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson for (EntityDelta state : mState) { 486ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson state.setProfileQueryUri(); 487ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 488ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 489eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 490eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 4911ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov bindEditors(); 4921ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 4931ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov 4941ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov /** 4951ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov * Merges extras from the intent. 4961ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov */ 4971ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov public void setIntentExtras(Bundle extras) { 4981ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov if (extras == null || extras.size() == 0) { 4991ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov return; 500bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 501916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 502a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 5031ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov for (EntityDelta state : mState) { 5041ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov final String accountType = state.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 5052b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = state.getValues().getAsString(RawContacts.DATA_SET); 5062b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type = accountTypes.getAccountType(accountType, dataSet); 50769f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (!type.readOnly) { 5081ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov // Apply extras to the first writable raw contact only 50969f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.parseExtras(mContext, type, state, extras); 5101ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov break; 5111ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 5121ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 513f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 514cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 515d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 516d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Shows the account creation screen. An account associated with the contact is automatically 517d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * selected. If there's no available account, device-local contact should be created. 518d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 519d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void createContact() { 5202b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 521a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov AccountTypeManager.getInstance(mContext).getAccounts(true); 522ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // No Accounts available or creating a local profile. Create a phone-local contact. 523ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (accounts.isEmpty() || mNewLocalProfile) { 52440bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(null); 525f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; // Don't show a dialog. 526f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 527cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 528d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // We have an account switcher in "create-account" screen, so don't need to ask a user to 529d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // select an account here. 530d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa createContact(accounts.get(0)); 531cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 532cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 533d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 534cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 535d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Shows account creation screen associated with a given account. 536d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 537d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param account may be null to signal a device-local contact should be created. 538cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 5392b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void createContact(AccountWithDataSet account) { 540a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 541b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType accountType = 5422b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro accountTypes.getAccountType(account != null ? account.type : null, 5432b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro account != null ? account.dataSet : null); 544fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 545b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (accountType.getCreateContactActivityClassName() != null) { 546fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 547fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomCreateContactActivityRequested(account, mIntentExtras); 548fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 549fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 550b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov bindEditorsForNewContact(account, accountType); 551fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 552fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 553fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 554d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa /** 555d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Removes a current editor ({@link #mState}) and rebinds new editor for a new account. 556d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * Some of old data are reused with new restriction enforced by the new account. 557d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * 5582b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro * @param oldState Old data being edited. 559d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param oldAccount Old account associated with oldState. 560d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa * @param newAccount New account to be used. 561d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa */ 562d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void rebindEditorsForNewContact( 5632b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro EntityDelta oldState, AccountWithDataSet oldAccount, AccountWithDataSet newAccount) { 564d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 5652b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType oldAccountType = accountTypes.getAccountType( 5662b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro oldAccount.type, oldAccount.dataSet); 5672b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountType newAccountType = accountTypes.getAccountType( 5682b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro newAccount.type, newAccount.dataSet); 569d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 570d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccountType.getCreateContactActivityClassName() != null) { 571d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa Log.w(TAG, "external activity called in rebind situation"); 572d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (mListener != null) { 573d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras); 574d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 575d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 576d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa mState = null; 577d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType); 578d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 579d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 580d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 5812b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet account, 5822b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType accountType) { 583d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa bindEditorsForNewContact(account, accountType, null, null); 584d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 585d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 5862b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro private void bindEditorsForNewContact(AccountWithDataSet newAccount, 5872b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType newAccountType, EntityDelta oldState, AccountType oldAccountType) { 588a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov mStatus = Status.EDITING; 589a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 590f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentValues values = new ContentValues(); 591d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (newAccount != null) { 592d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa values.put(RawContacts.ACCOUNT_NAME, newAccount.name); 593d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa values.put(RawContacts.ACCOUNT_TYPE, newAccount.type); 5942b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.put(RawContacts.DATA_SET, newAccount.dataSet); 595f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 596f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_NAME); 597f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_TYPE); 5982b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.putNull(RawContacts.DATA_SET); 599cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 600cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 601f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values)); 602d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (oldState == null) { 603d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa // Parse any values from incoming intent 604d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras); 605d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } else { 606d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.migrateStateForNewContact(mContext, oldState, insert, 607d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa oldAccountType, newAccountType); 608d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 609f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 61069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov // Ensure we have some default fields (if the account type does not support a field, 611362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmann // ensureKind will not add it, so it is safe to add e.g. Event) 612d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE); 613d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE); 614d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE); 615d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE); 616d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa EntityModifier.ensureKindExists(insert, newAccountType, StructuredPostal.CONTENT_ITEM_TYPE); 617f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 618ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson // Set the correct URI for saving the contact as a profile 619ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (mNewLocalProfile) { 620ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson insert.setProfileQueryUri(); 621ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson } 622ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson 623f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mState == null) { 624f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Create state if none exists yet 625ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = EntityDeltaList.fromSingle(insert); 626f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 627f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add contact onto end of existing state 628f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mState.add(insert); 629cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 630f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 631eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = true; 632eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 633f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 634cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 635cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 636f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void bindEditors() { 637f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 638f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 639cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 640f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 641f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 642cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 643f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 644f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 645a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 646a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan int numRawContacts = mState.size(); 647a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan for (int i = 0; i < numRawContacts; i++) { 648f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 649f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final EntityDelta entity = mState.get(i); 650f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ValuesDelta values = entity.getValues(); 651f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!values.isVisible()) continue; 652f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 653f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 6542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = values.getAsString(RawContacts.DATA_SET); 6552b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type = accountTypes.getAccountType(accountType, dataSet); 656f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long rawContactId = values.getAsLong(RawContacts._ID); 657f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 65872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor; 65969f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (type.isExternal()) { 660fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov editor = (BaseRawContactEditorView) inflater.inflate( 661fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov R.layout.external_raw_contact_editor_view, mContent, false); 662fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ((ExternalRawContactEditorView) editor).setListener(this); 663fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 664fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view, 665fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mContent, false); 666cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 667a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan if (Intent.ACTION_INSERT.equals(mAction) && numRawContacts == 1) { 6682b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final List<AccountWithDataSet> accounts = 669d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa AccountTypeManager.getInstance(mContext).getAccounts(true); 670ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (accounts.size() > 1 && !mNewLocalProfile) { 671d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa addAccountSwitcher(mState.get(0), editor); 672a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan } else { 673a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan disableAccountSwitcher(editor); 674d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 675d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 676a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan 67702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov editor.setEnabled(mEnabled); 678cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 679f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 6807d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 68169f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov editor.setState(entity, type, mViewIdGenerator); 682f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 6839442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann editor.getPhotoEditor().setEditorListener( 68469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov new PhotoEditorListener(editor, type.readOnly)); 68572af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (editor instanceof RawContactEditorView) { 68672af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final RawContactEditorView rawContactEditor = (RawContactEditorView) editor; 6875ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov EditorListener listener = new EditorListener() { 688f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 689f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 690f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onRequest(int request) { 6912bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) { 69211bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov acquireAggregationSuggestions(rawContactEditor); 69311bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 694f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 695f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 696f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 6972293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor removedEditor) { 698f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 6995ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov }; 7005ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov 7015ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor(); 7025ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov if (mRequestFocus) { 7035ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.requestFocus(); 7045ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov mRequestFocus = false; 7055ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov } 7065ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov nameEditor.setEditorListener(listener); 707f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 7085ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final TextFieldsEditorView phoneticNameEditor = 7095ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov rawContactEditor.getPhoneticNameEditor(); 7105ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov phoneticNameEditor.setEditorListener(listener); 7117d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup); 7127d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 7139302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactId == mAggregationSuggestionsRawContactId) { 714f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov acquireAggregationSuggestions(rawContactEditor); 715f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 716f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 717cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 718f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 719eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov mRequestFocus = false; 720eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 721e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 722e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 723f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 724f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 725a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 726a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann // Refresh Action Bar as the visibility of the join command 727825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Activity can be null if we have been detached from the Activity 728825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann final Activity activity = getActivity(); 729825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (activity != null) activity.invalidateOptionsMenu(); 730eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 731cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 732cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 733e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private void bindGroupMetaData() { 734e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov if (mGroupMetaData == null) { 735e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov return; 736e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 737e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 738e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov int editorCount = mContent.getChildCount(); 739e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov for (int i = 0; i < editorCount; i++) { 74072af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann BaseRawContactEditorView editor = (BaseRawContactEditorView) mContent.getChildAt(i); 741e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov editor.setGroupMetaData(mGroupMetaData); 742e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 743e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 744e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 745d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa private void addAccountSwitcher( 746d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final EntityDelta currentState, BaseRawContactEditorView editor) { 747d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa ValuesDelta values = currentState.getValues(); 7482b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountWithDataSet currentAccount = new AccountWithDataSet( 749d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa values.getAsString(RawContacts.ACCOUNT_NAME), 7502b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.getAsString(RawContacts.ACCOUNT_TYPE), 7512b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro values.getAsString(RawContacts.DATA_SET)); 752d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final View accountView = editor.findViewById(R.id.account); 753fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan final View anchorView = editor.findViewById(R.id.account_container); 754d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa accountView.setOnClickListener(new View.OnClickListener() { 755d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 756d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onClick(View v) { 757d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa final ListPopupWindow popup = new ListPopupWindow(mContext, null); 758a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa final AccountsListAdapter adapter = 759a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa new AccountsListAdapter(mContext, true, currentAccount); 760d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setWidth(anchorView.getWidth()); 761d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAnchorView(anchorView); 762d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setAdapter(adapter); 763d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setModal(true); 764d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 765d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.setOnItemClickListener(new AdapterView.OnItemClickListener() { 766d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa @Override 767d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa public void onItemClick(AdapterView<?> parent, View view, int position, 768d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa long id) { 769d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.dismiss(); 7702b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro AccountWithDataSet newAccount = adapter.getItem(position); 771d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa if (!newAccount.equals(currentAccount)) { 772d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa rebindEditorsForNewContact(currentState, currentAccount, newAccount); 773d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 774d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 775d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 776d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa popup.show(); 777d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 778d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa }); 779d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa } 780d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa 781a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan private void disableAccountSwitcher(BaseRawContactEditorView editor) { 782a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan // Remove the pressed state from the account header because the user cannot switch accounts 783a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan // on an existing contact 784a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan final View accountView = editor.findViewById(R.id.account); 785a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan accountView.setBackgroundDrawable(null); 786a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan accountView.setEnabled(false); 787a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan } 788a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan 789b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 790eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 791c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan inflater.inflate(R.menu.edit_contact, menu); 792cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 793cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 794b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 795eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onPrepareOptionsMenu(Menu menu) { 7969b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible 7979b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // because the custom action bar contains the "save" button now (not the overflow menu). 7989b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()? 7999b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan menu.findItem(R.id.menu_done).setVisible(false); 8009b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 80103587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson // Split only if more than one raw profile and not a user profile 80203587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson menu.findItem(R.id.menu_split).setVisible(mState != null && mState.size() > 1 && 8032bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson !isEditingUserProfile()); 80403587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson // Cannot join a user profile 8052bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson menu.findItem(R.id.menu_join).setVisible(!isEditingUserProfile()); 80603587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 80703587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson 80802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int size = menu.size(); 80902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < size; i++) { 81002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov menu.getItem(i).setEnabled(mEnabled); 81102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 812cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 813cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 814b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 815cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public boolean onOptionsItemSelected(MenuItem item) { 816cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (item.getItemId()) { 817f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_done: 8189df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.CLOSE); 819f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_discard: 820d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return revert(); 821f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_split: 822f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSplitContactAction(); 823f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_join: 824f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doJoinContactAction(); 825f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 826f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 827f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 828cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 829f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSplitContactAction() { 830f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 831f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 832a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann final SplitContactConfirmationDialogFragment dialog = 8334a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann new SplitContactConfirmationDialogFragment(); 8344a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.setTargetFragment(this, 0); 8354a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG); 836f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 837f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 838f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 839f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doJoinContactAction() { 8404c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov if (!hasValidState()) { 8414c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov return false; 8424c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 8434c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 8444c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // If we just started creating a new contact and haven't added any data, it's too 8454c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // early to do a join 846a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 847a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (mState.size() == 1 && mState.get(0).isContactInsert() 848a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov && !EntityModifier.hasChanges(mState, accountTypes)) { 849a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(getActivity(), R.string.toast_join_with_empty_contact, 850a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.LENGTH_LONG).show(); 851a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov return true; 8524c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 8534c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 8549df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.JOIN); 855f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 856f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 8570a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro private void loadPhotoPickSize() { 8580a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro Cursor c = mContext.getContentResolver().query(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI, 8590a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro new String[]{DisplayPhoto.DISPLAY_MAX_DIM}, null, null, null); 8600a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro try { 8610a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro c.moveToFirst(); 8620a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro mPhotoPickSize = c.getInt(0); 8630a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro } finally { 8640a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro c.close(); 8650a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro } 8660a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro } 8670a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro 868f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 869f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for picking a photo from Gallery, cropping it and returning the bitmap. 870f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 8710a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro public Intent getPhotoPickIntent() { 872f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); 873f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setType("image/*"); 874f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("crop", "true"); 875f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectX", 1); 876f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectY", 1); 8770a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro intent.putExtra("outputX", mPhotoPickSize); 8780a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro intent.putExtra("outputY", mPhotoPickSize); 879f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("return-data", true); 880f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 881f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 882f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 883f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 884f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Check if our internal {@link #mState} is valid, usually checked before 885f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * performing user actions. 886f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 887f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean hasValidState() { 888f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return mState != null && mState.size() > 0; 889f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 890f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 891f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 892f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Create a file name for the icon photo using current time. 893f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 894f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String getPhotoFileName() { 895f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Date date = new Date(System.currentTimeMillis()); 896f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("'IMG'_yyyyMMdd_HHmmss"); 897f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return dateFormat.format(date) + ".jpg"; 898f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 899f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 900f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 901f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for capturing a photo and storing it in a temporary file. 902f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 903f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getTakePickIntent(File f) { 904f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, null); 905f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); 906f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 907f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 908f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 909f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 910f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Sends a newly acquired photo to Gallery for cropping 911f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 912f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void doCropPhoto(File f) { 913f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 914f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add the image to the media store 915f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann MediaScannerConnection.scanFile( 916f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext, 917f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[] { f.getAbsolutePath() }, 918f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[] { null }, 919f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann null); 920f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 921f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Launch gallery to crop the photo 922f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = getCropImageIntent(Uri.fromFile(f)); 923f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.SUB_ACTIVITY; 924a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_PHOTO_PICKED_WITH_DATA); 925f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (Exception e) { 926f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.e(TAG, "Cannot crop image", e); 927f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show(); 928cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 929cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 930cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 931f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 932f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for image cropping. 933f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 9340a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro public Intent getCropImageIntent(Uri photoUri) { 935f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent("com.android.camera.action.CROP"); 936f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setDataAndType(photoUri, "image/*"); 937f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("crop", "true"); 938f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectX", 1); 939f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectY", 1); 9400a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro intent.putExtra("outputX", mPhotoPickSize); 9410a2a5db3b3633883388953dc98e30c2edd7cae62Dave Santoro intent.putExtra("outputY", mPhotoPickSize); 942f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("return-data", true); 943f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 944f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 945f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 946f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 947f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Saves or creates the contact based on the mode, and if successful 948f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * finishes the activity. 949f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 9509df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public boolean save(int saveMode) { 951a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 952f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 953f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 954f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 9558c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov // If we are about to close the editor - there is no need to refresh the data 956a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.SPLIT) { 9579d2bcfb40d0ee107886eb99eba13a840e944ba43Dianne Hackborn getLoaderManager().destroyLoader(LOADER_DATA); 9588c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov } 9598c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov 960825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.SAVING; 9616cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 962a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 963a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (!EntityModifier.hasChanges(mState, accountTypes)) { 964a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov onSaveCompleted(false, saveMode, mLookupUri); 9656cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov return true; 9666cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov } 9676cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 968a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov setEnabled(false); 969f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 970a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Intent intent = ContactSaveService.createSaveContactIntent(getActivity(), mState, 9712bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(), 972ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson getActivity().getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED); 973a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov getActivity().startService(intent); 974f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 975f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 976f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 977d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static class CancelEditDialogFragment extends DialogFragment { 978d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 979d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static void show(ContactEditorFragment fragment) { 980d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment dialog = new CancelEditDialogFragment(); 981d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.setTargetFragment(fragment, 0); 982d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.show(fragment.getFragmentManager(), "cancelEditor"); 983d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 984d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 985d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 986d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 987d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov AlertDialog dialog = new AlertDialog.Builder(getActivity()) 9884292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 989d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setTitle(R.string.cancel_confirmation_dialog_title) 990d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setMessage(R.string.cancel_confirmation_dialog_message) 9911ba8b6fea4c3f82ded19305874e72a326612aed1Katherine Kuan .setPositiveButton(android.R.string.ok, 992d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov new DialogInterface.OnClickListener() { 993d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 994d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 995d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ((ContactEditorFragment)getTargetFragment()).doRevertAction(); 996d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 997d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 998d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ) 999d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setNegativeButton(android.R.string.cancel, null) 1000d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .create(); 1001d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return dialog; 1002d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1003d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1004d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1005d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private boolean revert() { 1006c863b0171f2a54a0ee71b34b33034aeea2464ccaDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1007c863b0171f2a54a0ee71b34b33034aeea2464ccaDmitri Plotnikov if (mState == null || !EntityModifier.hasChanges(mState, accountTypes)) { 1008d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov doRevertAction(); 1009d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } else { 1010d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment.show(this); 1011d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1012d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return true; 1013d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 1014d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 1015d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private void doRevertAction() { 1016825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // When this Fragment is closed we don't want it to auto-save 1017825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 101822fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onReverted(); 1019f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1020f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 10219b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan public void doSaveAction() { 10229b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan save(SaveMode.CLOSE); 10239b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan } 10249b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan 10252b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov public void onJoinCompleted(Uri uri) { 1026a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov onSaveCompleted(false, SaveMode.RELOAD, uri); 10272b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov } 10282b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov 1029a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public void onSaveCompleted(boolean hadChanges, int saveMode, Uri contactLookupUri) { 1030a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov boolean success = contactLookupUri != null; 1031a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Log.d(TAG, "onSaveCompleted(" + saveMode + ", " + contactLookupUri); 1032a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (hadChanges) { 1033a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (success) { 1034a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode != SaveMode.JOIN) { 1035a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 1036a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1037a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else { 1038a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 1039a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1040a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 1041f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 104215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.CLOSE: 10439df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov case SaveMode.HOME: 1044f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 1045f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (success && contactLookupUri != null) { 1046b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann final String requestAuthority = 1047b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri == null ? null : mLookupUri.getAuthority(); 1048f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1049f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String legacyAuthority = "contacts"; 1050f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1051f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = new Intent(); 10525649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan resultIntent.setAction(Intent.ACTION_VIEW); 1053f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (legacyAuthority.equals(requestAuthority)) { 1054f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Build legacy Uri when requested by caller 1055f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(Contacts.lookupContact( 1056f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.getContentResolver(), contactLookupUri)); 1057f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyContentUri = Uri.parse("content://contacts/people"); 1058f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyUri = ContentUris.withAppendedId( 1059f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann legacyContentUri, contactId); 1060f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(legacyUri); 1061f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1062f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Otherwise pass back a lookup-style Uri 1063f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(contactLookupUri); 1064f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1065f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1066f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 1067f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 1068f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1069825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // It is already saved, so prevent that it is saved again 1070825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 10715649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan if (mListener != null) mListener.onSaveFinished(resultIntent); 1072f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1073a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 107415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.RELOAD: 1075dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov case SaveMode.JOIN: 107615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann if (success && contactLookupUri != null) { 1077623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann // If it was a JOIN, we are now ready to bring up the join activity. 1078623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann if (saveMode == SaveMode.JOIN) { 1079623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann showJoinAggregateActivity(contactLookupUri); 1080623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann } 1081623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann 108215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If this was in INSERT, we are changing into an EDIT now. 108315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If it already was an EDIT, we are changing to the new Uri now 108415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann mState = null; 10851015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov load(Intent.ACTION_EDIT, contactLookupUri, null); 1086825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.LOADING; 108715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener); 108815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 108915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann break; 1090a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 109115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.SPLIT: 1092a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mStatus = Status.CLOSING; 1093a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann if (mListener != null) { 10948c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov mListener.onContactSplit(contactLookupUri); 1095a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } else { 1096a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann Log.d(TAG, "No listener registered, can not call onSplitFinished"); 1097a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1098f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1099f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1100f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1101f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1102f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1103f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 1104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 1105f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 1106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 110873a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov if (contactLookupUri == null || !isAdded()) { 1109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 1110f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1111f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1112f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 1113623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann mContactWritableForJoin = isContactWritable(); 1114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = new Intent(JoinContactActivity.JOIN_CONTACT); 1115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(JoinContactActivity.EXTRA_TARGET_CONTACT_ID, mContactIdForJoin); 1116a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_JOIN); 1117f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1118f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1119f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1120f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 1121f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 1122f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 11232b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin, 1124623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann contactId, mContactWritableForJoin, 11252b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED); 11262b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov mContext.startService(intent); 1127f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1128f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1129f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1130ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov * Returns true if there is at least one writable raw contact in the current contact. 1131ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov */ 1132ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov private boolean isContactWritable() { 1133a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1134ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov int size = mState.size(); 1135ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov for (int i = 0; i < size; i++) { 1136ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov ValuesDelta values = mState.get(i).getValues(); 1137ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 11382b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final String dataSet = values.getAsString(RawContacts.DATA_SET); 11392b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type = accountTypes.getAccountType(accountType, dataSet); 114069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (!type.readOnly) { 1141ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return true; 1142ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1143ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1144ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return false; 1145ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 1146ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov 11472bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson private boolean isEditingUserProfile() { 11482bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson return mNewLocalProfile || mIsUserProfile; 11492bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson } 11502bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson 1151cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public static interface Listener { 1152cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 115322fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was not found, so somehow close this fragment. This is raised after a contact 115422fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * is removed via Menu/Delete (unless it was a new contact) 1155cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 115622fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onContactNotFound(); 1157f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1158f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 11598c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov * Contact was split, so we can close now. 1160a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * @param newLookupUri The lookup uri of the new contact that should be shown to the user. 1161a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * The editor tries best to chose the most natural contact here. 1162f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 11638c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov void onContactSplit(Uri newLookupUri); 1164f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1165f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1166f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User has tapped Revert, close the fragment now. 1167f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 116822fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onReverted(); 1169f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1170f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 117122fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was saved and the Fragment can now be closed safely. 1172f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 11735649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan void onSaveFinished(Intent resultIntent); 1174b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann 1175b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann /** 1176e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * User switched to editing a different contact (a suggestion from the 1177e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * aggregation engine). 1178e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov */ 1179e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov void onEditOtherContactRequested( 1180e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov Uri contactLookupUri, ArrayList<ContentValues> contentValues); 1181fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1182fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1183fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * Contact is being created for an external account that provides its own 1184fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * new contact activity. 1185fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 11862b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro void onCustomCreateContactActivityRequested(AccountWithDataSet account, 11872b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro Bundle intentExtras); 1188fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1189fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1190fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * The edited raw contact belongs to an external account that provides 1191fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * its own edit activity. 1192fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * 1193fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * @param redirect indicates that the current editor should be closed 1194fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * before the custom editor is shown. 1195fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 11962b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro void onCustomEditContactActivityRequested(AccountWithDataSet account, Uri rawContactUri, 1197fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Bundle intentExtras, boolean redirect); 1198f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1199f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1200f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private class EntityDeltaComparator implements Comparator<EntityDelta> { 1201f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Compare EntityDeltas for sorting the stack of editors. 1203f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 12044a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann @Override 1205f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public int compare(EntityDelta one, EntityDelta two) { 1206f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check direct equality 1207f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (one.equals(two)) { 1208f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 0; 1209f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1210f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1211a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 12122b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountType1 = one.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 12132b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet1 = one.getValues().getAsString(RawContacts.DATA_SET); 12142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type1 = accountTypes.getAccountType(accountType1, dataSet1); 12152b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String accountType2 = two.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 12162b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro String dataSet2 = two.getValues().getAsString(RawContacts.DATA_SET); 12172b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro final AccountType type2 = accountTypes.getAccountType(accountType2, dataSet2); 1218f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1219f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check read-only 1220b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (type1.readOnly && !type2.readOnly) { 1221f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1222b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov } else if (!type1.readOnly && type2.readOnly) { 1223f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1224f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1225f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1226f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account type 1227f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean skipAccountTypeCheck = false; 1228b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount1 = type1 instanceof GoogleAccountType; 1229b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount2 = type2 instanceof GoogleAccountType; 123069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (isGoogleAccount1 && !isGoogleAccount2) { 1231f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 123269f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (!isGoogleAccount1 && isGoogleAccount2) { 1233f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 123469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (isGoogleAccount1 && isGoogleAccount2){ 1235f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann skipAccountTypeCheck = true; 1236f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1237f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1238f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int value; 1239f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!skipAccountTypeCheck) { 1240b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (type1.accountType == null) { 12412776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru return 1; 12422776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru } 1243b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov value = type1.accountType.compareTo(type2.accountType); 1244f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1245f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 12462b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else { 12472b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro // Fall back to data set. 12482b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (type1.dataSet != null) { 12492b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro value = type1.dataSet.compareTo(type2.dataSet); 12502b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro if (value != 0) { 12512b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return value; 12522b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 12532b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } else if (type2.dataSet != null) { 12542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro return 1; 12552b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro } 1256f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1257f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1258f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1259f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account name 1260f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta oneValues = one.getValues(); 1261f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String oneAccount = oneValues.getAsString(RawContacts.ACCOUNT_NAME); 1262f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneAccount == null) oneAccount = ""; 1263f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta twoValues = two.getValues(); 1264f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String twoAccount = twoValues.getAsString(RawContacts.ACCOUNT_NAME); 1265f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (twoAccount == null) twoAccount = ""; 1266f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann value = oneAccount.compareTo(twoAccount); 1267f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1268f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 1269f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1270f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1271f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Both are in the same account, fall back to contact ID 1272f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long oneId = oneValues.getAsLong(RawContacts._ID); 1273f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long twoId = twoValues.getAsLong(RawContacts._ID); 1274f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneId == null) { 1275f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1276f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoId == null) { 1277f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1278f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1279f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1280f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return (int)(oneId - twoId); 1281f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1282f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1283f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1284f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1285f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Returns the contact ID for the currently edited contact or 0 if the contact is new. 1286f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1287f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected long getContactId() { 1288c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov if (mState != null) { 1289c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov for (EntityDelta rawContact : mState) { 1290c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID); 1291c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov if (contactId != null) { 1292c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov return contactId; 1293c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov } 1294f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1295f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1296f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return 0; 1297f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1298f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1299f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1300f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Triggers an asynchronous search for aggregation suggestions. 1301f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 130272af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann public void acquireAggregationSuggestions(RawContactEditorView rawContactEditor) { 13039302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov long rawContactId = rawContactEditor.getRawContactId(); 13049302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (mAggregationSuggestionsRawContactId != rawContactId 13059302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov && mAggregationSuggestionView != null) { 13069302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 13079302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = null; 13089302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionEngine.reset(); 13099302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 13109302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 13119302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = rawContactId; 13129302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 1313f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine == null) { 1314f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine = new AggregationSuggestionEngine(getActivity()); 1315f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.setListener(this); 1316f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.start(); 1317f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1318f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1319916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mAggregationSuggestionEngine.setContactId(getContactId()); 1320916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 1321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann LabeledEditorView nameEditor = rawContactEditor.getNameEditor(); 1322f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.onNameChange(nameEditor.getValues()); 1323f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1324f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1325f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 1326f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onAggregationSuggestionChange() { 1327a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!isAdded() || mState == null || mStatus != Status.EDITING) { 132802cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov return; 132902cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov } 133002cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov 13316c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionPopup != null && mAggregationSuggestionPopup.isShowing()) { 13326c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.dismiss(); 13339302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1334f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 13356c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) { 1336f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 1337f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1338f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 13396c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final RawContactEditorView rawContactView = 13406c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId); 134102a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki if (rawContactView == null) { 134202a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki return; // Raw contact deleted? 134302a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki } 13446c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa final View anchorView = rawContactView.findViewById(R.id.anchor_view); 13456c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup = new ListPopupWindow(mContext, null); 13466c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAnchorView(anchorView); 13476c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setWidth(anchorView.getWidth()); 13486c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 13496c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setModal(true); 13506c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setAdapter( 13516c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa new AggregationSuggestionAdapter(getActivity(), 13526c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mState.size() == 1 && mState.get(0).isContactInsert(), 13536c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa this, mAggregationSuggestionEngine.getSuggestions())); 13546c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.setOnItemClickListener(mAggregationSuggestionItemClickListener); 13556c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa mAggregationSuggestionPopup.show(); 1356bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1357bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1358bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1359bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onJoinAction(long contactId, List<Long> rawContactIdList) { 1360bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = new long[rawContactIdList.size()]; 1361bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov for (int i = 0; i < rawContactIds.length; i++) { 1362bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov rawContactIds[i] = rawContactIdList.get(i); 1363bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1364bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov JoinSuggestedContactDialogFragment dialog = 1365bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new JoinSuggestedContactDialogFragment(); 1366bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1367bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putLongArray("rawContactIds", rawContactIds); 1368bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1369bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 137074f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov try { 137174f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov dialog.show(getFragmentManager(), "join"); 137274f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } catch (Exception ex) { 137374f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov // No problem - the activity is no longer available to display the dialog 137474f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } 1375bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1376bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1377bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class JoinSuggestedContactDialogFragment extends DialogFragment { 1378bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1379bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1380bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1381bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 13824292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1383bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setTitle(R.string.aggregation_suggestion_join_dialog_title) 1384bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_join_dialog_message) 1385bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1386bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1387bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1388bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1389bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1390bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = 1391bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getLongArray("rawContactIds"); 1392bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doJoinSuggestedContact(rawContactIds); 1393bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1394bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1395bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1396bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1397bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1398bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1399bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1400bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1401bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1402bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Joins the suggested contact (specified by the id's of constituent raw 1403bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * contacts), save all changes, and stay in the editor. 1404bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1405bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doJoinSuggestedContact(long[] rawContactIds) { 1406cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1407cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov return; 1408cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov } 1409cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov 1410bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mState.setJoinWithRawContacts(rawContactIds); 14119df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 1412bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1413bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1414bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1415bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onEditAction(Uri contactLookupUri) { 1416bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov SuggestionEditConfirmationDialogFragment dialog = 1417bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new SuggestionEditConfirmationDialogFragment(); 1418bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1419bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putParcelable("contactUri", contactLookupUri); 1420bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1421bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 1422bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.show(getFragmentManager(), "edit"); 1423bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1424bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1425bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class SuggestionEditConfirmationDialogFragment extends DialogFragment { 1426bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1427bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1428bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1429bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 14304292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1431bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setTitle(R.string.aggregation_suggestion_edit_dialog_title) 1432bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_edit_dialog_message) 1433bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1434bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1435bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1436bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1437bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1438bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Uri contactUri = 1439bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getParcelable("contactUri"); 1440bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doEditSuggestedContact(contactUri); 1441bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1442bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1443bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1444bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1445bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1446bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1447bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1448bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1449bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1450bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Abandons the currently edited contact and switches to editing the suggested 1451bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * one, transferring all the data there 1452bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1453bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doEditSuggestedContact(Uri contactUri) { 1454bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov if (mListener != null) { 1455a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann // make sure we don't save this contact when closing down 1456a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann mStatus = Status.CLOSING; 1457bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mListener.onEditOtherContactRequested( 1458bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov contactUri, mState.get(0).getContentValues()); 1459bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1460bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1461bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1462a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov public void setAggregationSuggestionViewEnabled(boolean enabled) { 1463a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (mAggregationSuggestionView == null) { 1464a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov return; 1465a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1466a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1467a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 1468a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov R.id.aggregation_suggestions); 1469a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov int count = itemList.getChildCount(); 1470a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov for (int i = 0; i < count; i++) { 1471a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov itemList.getChildAt(i).setEnabled(enabled); 1472a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1473a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1474a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1475f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1476f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Computes bounds of the supplied view relative to its ascendant. 1477f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1478f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private Rect getRelativeBounds(View ascendant, View view) { 1479f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Rect rect = new Rect(); 1480f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov rect.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); 1481f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1482f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov View parent = (View) view.getParent(); 1483f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov while (parent != ascendant) { 1484f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov rect.offset(parent.getLeft(), parent.getTop()); 1485f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov parent = (View) parent.getParent(); 1486f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1487f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return rect; 1488f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1489f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1490f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1491f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 1492b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann outState.putParcelable(KEY_URI, mLookupUri); 1493d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putString(KEY_ACTION, mAction); 1494d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 1495f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (hasValidState()) { 1496f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Store entities with modifications 1497f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_EDIT_STATE, mState); 1498f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1499f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1500f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 1501f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator); 1502f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mCurrentPhotoFile != null) { 1503f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putString(KEY_CURRENT_PHOTO_FILE, mCurrentPhotoFile.toString()); 1504f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1505f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 1506623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin); 15079302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov outState.putLong(KEY_SHOW_JOIN_SUGGESTIONS, mAggregationSuggestionsRawContactId); 150802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov outState.putBoolean(KEY_ENABLED, mEnabled); 1509ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile); 1510ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile); 1511ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov outState.putInt(KEY_STATUS, mStatus); 1512f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 1513f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1514f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1515d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 1516f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 1517f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (mStatus == Status.SUB_ACTIVITY) { 1518f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.EDITING; 1519f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov } 1520f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 1521f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Ignore failed requests 1522f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (resultCode != Activity.RESULT_OK) return; 1523f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (requestCode) { 1524a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_PHOTO_PICKED_WITH_DATA: { 1525c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann // As we are coming back to this view, the editor will be reloaded automatically, 1526c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann // which will cause the photo that is set here to disappear. To prevent this, 15274a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann // we remember to set a flag which is interpreted after loading. 15284a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann // This photo is set here already to reduce flickering. 1529c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mPhoto = data.getParcelableExtra("data"); 1530c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann setPhoto(mRawContactIdRequestingPhoto, mPhoto); 1531c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mRawContactIdRequestingPhotoAfterLoad = mRawContactIdRequestingPhoto; 1532c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mRawContactIdRequestingPhoto = -1; 1533f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1534f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1535f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1536a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_CAMERA_WITH_DATA: { 1537f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doCropPhoto(mCurrentPhotoFile); 1538f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1539f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1540a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_JOIN: { 1541f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 1542f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 1543f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 1544f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 15454a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann break; 1546f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1547f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1548cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 15499cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 1550c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann /** 1551c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann * Sets the photo stored in mPhoto and writes it to the RawContact with the given id 1552c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann */ 1553c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann private void setPhoto(long rawContact, Bitmap photo) { 1554bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact); 15559302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestingEditor != null) { 15569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov requestingEditor.setPhotoBitmap(photo); 15579302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } else { 15589302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Log.w(TAG, "The contact that requested the photo is no longer present."); 15599302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 15609302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 15619302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 15629302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov /** 15639302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov * Finds raw contact editor view for the given rawContactId. 15649302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov */ 1565bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public BaseRawContactEditorView getRawContactEditorView(long rawContactId) { 1566c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 1567c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann final View childView = mContent.getChildAt(i); 156872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 156972af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 15709302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (editor.getRawContactId() == rawContactId) { 15719302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return editor; 1572c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1573c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1574c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 15759302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return null; 1576c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1577c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1578fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 1579fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann * Returns true if there is currently more than one photo on screen. 1580fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1581fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann private boolean hasMoreThanOnePhoto() { 1582fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int count = mContent.getChildCount(); 1583fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int countWithPicture = 0; 1584fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann for (int i = 0; i < count; i++) { 1585fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann final View childView = mContent.getChildAt(i); 1586fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (childView instanceof BaseRawContactEditorView) { 1587fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 1588fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (editor.hasSetPhoto()) { 1589fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann countWithPicture++; 1590fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (countWithPicture > 1) return true; 1591fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1592fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1593fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1594fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 1595fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann return false; 15969cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1597222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1598222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann /** 1599222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann * The listener for the data loader 1600222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann */ 1601222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener = 1602222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann new LoaderCallbacks<ContactLoader.Result>() { 1603222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1604222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) { 1605222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann mLoaderStartTime = SystemClock.elapsedRealtime(); 1606b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann return new ContactLoader(mContext, mLookupUri); 1607222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1608222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1609222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1610222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) { 1611222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long loaderCurrentTime = SystemClock.elapsedRealtime(); 1612222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime)); 16135da9363bc4f2e04dc388579e1df979a5843e25e6Dmitri Plotnikov if (data == ContactLoader.Result.NOT_FOUND || data == ContactLoader.Result.ERROR) { 1614222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann // Item has been deleted 1615222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.i(TAG, "No contact found. Closing activity"); 161622fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onContactNotFound(); 1617222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return; 1618222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1619222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1620825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.EDITING; 16216caccaeeed943db323be89853a108f422e670760Dmitri Plotnikov mLookupUri = data.getLookupUri(); 1622222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataStartTime = SystemClock.elapsedRealtime(); 1623222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann setData(data); 1624222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataEndTime = SystemClock.elapsedRealtime(); 1625c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1626c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann // If we are coming back from the photo trimmer, this will be set. 1627c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann if (mRawContactIdRequestingPhotoAfterLoad != -1) { 1628c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann setPhoto(mRawContactIdRequestingPhotoAfterLoad, mPhoto); 1629c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mRawContactIdRequestingPhotoAfterLoad = -1; 1630c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mPhoto = null; 1631c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1632222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime)); 1633222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 16344ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 1635623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann @Override 16364ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<ContactLoader.Result> loader) { 16374ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1638222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann }; 1639a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 1640e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov /** 1641be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan * The listener for the group meta data loader for all groups. 1642e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov */ 1643e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener = 1644e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov new LoaderCallbacks<Cursor>() { 1645e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1646e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1647e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public CursorLoader onCreateLoader(int id, Bundle args) { 1648be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI); 1649e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1650e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1651e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1652e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1653e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov mGroupMetaData = data; 1654e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 1655e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 16564ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 16574ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 16584ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1659e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov }; 1660e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1661a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann @Override 1662a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann public void onSplitContactConfirmed() { 1663a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann mState.markRawContactsForSplitting(); 16649df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.SPLIT); 1665a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1666a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 16679442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann private final class PhotoEditorListener 16689442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann implements EditorListener, PhotoActionPopup.Listener { 16699442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann private final BaseRawContactEditorView mEditor; 167069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov private final boolean mAccountReadOnly; 16719442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 167269f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov private PhotoEditorListener(BaseRawContactEditorView editor, boolean accountReadOnly) { 16739442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mEditor = editor; 167469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov mAccountReadOnly = accountReadOnly; 16759442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16769442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 16779442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 16789442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onRequest(int request) { 16799442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (!hasValidState()) return; 16809442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 16819442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (request == EditorListener.REQUEST_PICK_PHOTO) { 16829442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Determine mode 16839442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final int mode; 168469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (mAccountReadOnly) { 16859442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (mEditor.hasSetPhoto() && hasMoreThanOnePhoto()) { 16869442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_READ_ONLY_ALLOW_PRIMARY; 16879442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16889442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Read-only and either no photo or the only photo ==> no options 16899442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann return; 16909442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16919442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16929442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (mEditor.hasSetPhoto()) { 16939442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (hasMoreThanOnePhoto()) { 16949442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_PHOTO_ALLOW_PRIMARY; 16959442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16969442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_PHOTO_DISALLOW_PRIMARY; 16979442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16989442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16999442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_NO_PHOTO; 17009442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1701fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 17029442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann PhotoActionPopup.createPopupMenu(mContext, mEditor.getPhotoEditor(), this, mode) 17039442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann .show(); 1704fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1705fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1706fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 17079442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17082293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor removedEditor) { 17092293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // The picture cannot be deleted, it can only be removed, which is handled by 17102293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // onRemovePictureChosen() 17119442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1712a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17139442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17149442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * User has chosen to set the selected photo as the (super) primary photo 17159442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17169442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17179442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onUseAsPrimaryChosen() { 17189442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Set the IsSuperPrimary for each editor 17199442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann int count = mContent.getChildCount(); 17209442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann for (int i = 0; i < count; i++) { 17219442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final View childView = mContent.getChildAt(i); 17229442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 17239442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 17249442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final PhotoEditorView photoEditor = editor.getPhotoEditor(); 17259442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann photoEditor.setSuperPrimary(editor == mEditor); 17269442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17279442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1728a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1729a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17309442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17319442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * User has chosen to remove a picture 17329442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17339442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17342293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onRemovePictureChosen() { 17359442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mEditor.setPhotoBitmap(null); 1736a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1737a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17389442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17399442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * Launches Camera to take a picture and store it in a file. 17409442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17419442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17429442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onTakePhotoChosen() { 17439442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 17449442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann try { 17459442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Launch camera to take photo for selected contact 17469442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann PHOTO_DIR.mkdirs(); 17479442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mCurrentPhotoFile = new File(PHOTO_DIR, getPhotoFileName()); 17489442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final Intent intent = getTakePickIntent(mCurrentPhotoFile); 17499442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 1750f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.SUB_ACTIVITY; 17519442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_CAMERA_WITH_DATA); 17529442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } catch (ActivityNotFoundException e) { 17539442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, 17549442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.LENGTH_LONG).show(); 17559442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17569442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1757a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17589442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17599442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * Launches Gallery to pick a photo. 17609442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17619442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17629442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onPickFromGalleryChosen() { 17639442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 17649442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann try { 17659442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Launch picker to choose photo for selected contact 17669442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final Intent intent = getPhotoPickIntent(); 1767f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.SUB_ACTIVITY; 17689442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_PHOTO_PICKED_WITH_DATA); 17699442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } catch (ActivityNotFoundException e) { 17709442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, 17719442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.LENGTH_LONG).show(); 17729442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17734a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 17744a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 17752ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1776