ContactEditorFragment.java revision c863b0171f2a54a0ee71b34b33034aeea2464cca
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; 29f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityDelta; 30f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityDelta.ValuesDelta; 31ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmannimport com.android.contacts.model.EntityDeltaList; 32f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityModifier; 3335769b804fbfd5a1fc0b2c36cd0a786d662c4334Daniel Lehmannimport com.android.contacts.model.GoogleAccountType; 34f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 35f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.accounts.Account; 36cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity; 37bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.AlertDialog; 38bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.Dialog; 39bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.DialogFragment; 40222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.Fragment; 41222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager; 42222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks; 43cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ActivityNotFoundException; 44cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris; 45cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentValues; 46cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context; 47e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikovimport android.content.CursorLoader; 48bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface; 49e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikovimport android.content.Entity; 50cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent; 51cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader; 52f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor; 53f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap; 54f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.graphics.Rect; 55f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.media.MediaScannerConnection; 56cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri; 57cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle; 58f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.os.Environment; 599767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock; 60f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.provider.ContactsContract; 61cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email; 62362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Event; 63362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Note; 64362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Organization; 65cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone; 6641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 67362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 68362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Website; 69f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 702013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmannimport android.provider.ContactsContract.Intents; 71f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 72f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.MediaStore; 7341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikovimport android.text.TextUtils; 74cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log; 75cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater; 76cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu; 77cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater; 78cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem; 79cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View; 80cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup; 81f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.view.ViewGroup.LayoutParams; 82bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.view.ViewGroup.MarginLayoutParams; 83f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.view.ViewStub; 8480d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout; 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 969442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann SplitContactConfirmationDialogFragment.Listener, SelectAccountDialogFragment.Listener, 97fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener, 98fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ExternalRawContactEditorView.Listener { 99cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 100cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private static final String TAG = "ContactEditorFragment"; 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"; 1129302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions"; 11302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private static final String KEY_ENABLED = "enabled"; 114ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov private static final String KEY_STATUS = "status"; 115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 116a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public static final String SAVE_MODE_EXTRA_KEY = "saveMode"; 117a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 11815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 1197d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * An intent extra that forces the editor to add the edited contact 1207d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov * to the default group (e.g. "My Contacts"). 1217d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov */ 1227d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory"; 1237d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 1247d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov /** 12515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Modes that specify what the AsyncTask has to perform after saving 12615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 1279df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public interface SaveMode { 12815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 12915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Close the editor after saving 13015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 13115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int CLOSE = 0; 13215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 13315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 13415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Reload the data so that the user can continue editing 13515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 13615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int RELOAD = 1; 13715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 13815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 13915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Split the contact after saving 14015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int SPLIT = 2; 14215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann 14315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann /** 14415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann * Join another contact after saving 14515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann */ 14615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann public static final int JOIN = 3; 1479df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov 1489df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov /** 1499df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov * Navigate to Contacts Home activity after saving. 1509df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov */ 1519df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public static final int HOME = 4; 15215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 153a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 154825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann private interface Status { 155825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 156825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * The loader is fetching data 157825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 158825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int LOADING = 0; 159825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 160825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 161825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann * Not currently busy. We are waiting for the user to enter data 162825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 163825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int EDITING = 1; 164825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 165825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 166f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * The data is currently being saved. This is used to prevent more 167f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * auto-saves (they shouldn't overlap) 168825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 169825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int SAVING = 2; 170825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 171825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann /** 172f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * Prevents any more savings (this is used if Save/Close or Revert was 173f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * executed by the user) 174825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann */ 175825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann public static final int CLOSING = 3; 176f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 177f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov /** 178f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov * Prevents saving while running a child activity. 179f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov */ 180f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov public static final int SUB_ACTIVITY = 4; 181825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 182825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 183a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_JOIN = 0; 184a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_CAMERA_WITH_DATA = 1; 185a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann private static final int REQUEST_CODE_PHOTO_PICKED_WITH_DATA = 2; 186f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 187c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann private Bitmap mPhoto = null; 188f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mRawContactIdRequestingPhoto = -1; 189c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann private long mRawContactIdRequestingPhotoAfterLoad = -1; 190cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 191f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private final EntityDeltaComparator mComparator = new EntityDeltaComparator(); 192f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 193f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final int ICON_SIZE = 96; 194f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 195f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private static final File PHOTO_DIR = new File( 196f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Environment.getExternalStorageDirectory() + "/DCIM/Camera"); 197f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 198e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private Cursor mGroupMetaData; 199e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 200f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 201f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * A delay in milliseconds used for bringing aggregation suggestions to 202f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * the visible part of the screen. The reason this has to be done after 203f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * a delay is a race condition with the soft keyboard. The keyboard 204f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * may expand to display its own autocomplete suggestions, which will 205f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * reduce the visible area of the screen. We will yield to the keyboard 206f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * hoping that the delay is sufficient. If not - part of the 207f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * suggestion will be hidden, which is not fatal. 208f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 209f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private static final int AGGREGATION_SUGGESTION_SCROLL_DELAY = 200; 210f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 211f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private File mCurrentPhotoFile; 212cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 213cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Context mContext; 214f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String mAction; 215b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann private Uri mLookupUri; 216f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private Bundle mIntentExtras; 217cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann private Listener mListener; 218cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 219f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private long mContactIdForJoin; 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 2347d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov private boolean mAutoAddToDefaultGroup; 2357d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 23602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov private boolean mEnabled = true; 23702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 238cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public ContactEditorFragment() { 239cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 240cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 24102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public void setEnabled(boolean enabled) { 24202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mEnabled != enabled) { 24302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = enabled; 24402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mContent != null) { 24502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int count = mContent.getChildCount(); 24602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < count; i++) { 24702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mContent.getChildAt(i).setEnabled(enabled); 24802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 24902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 250a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov setAggregationSuggestionViewEnabled(enabled); 25102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov final Activity activity = getActivity(); 25202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (activity != null) activity.invalidateOptionsMenu(); 25302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 25402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 25502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 256cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 257cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public void onAttach(Activity activity) { 258cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann super.onAttach(activity); 259cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann mContext = activity; 260cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 261cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 262cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 263f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onStop() { 264f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov super.onStop(); 265f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine != null) { 266f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.quit(); 267f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 268248fba273e867616b1f8973dac6ce3e5ee1ba544Dmitri Plotnikov 269825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If anything was left unsaved, save it now but keep the editor open. 270f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) { 2719df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 272825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 273f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 274f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 275f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 276cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 277cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false); 278cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 279f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent = (LinearLayout) view.findViewById(R.id.editors); 280e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann 2813648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann setHasOptionsMenu(true); 282cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 283825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // If we are in an orientation change, we already have mState (it was loaded by onCreate) 284825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (mState != null) { 285825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann bindEditors(); 286825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 287825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 288cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann return view; 289cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 290cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 291222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 292222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onActivityCreated(Bundle savedInstanceState) { 293222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann super.onActivityCreated(savedInstanceState); 294222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 295825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann Log.d(TAG, "onActivityCreated(" + savedInstanceState + ")"); 296222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 297825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Handle initial actions only when existing state missing 2984a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann final boolean hasIncomingState = savedInstanceState != null; 299825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 300825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (!hasIncomingState) { 301825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (Intent.ACTION_EDIT.equals(mAction)) { 302825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (mListener != null) mListener.setTitleTo(R.string.editContact_title_edit); 303825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener); 304825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } else if (Intent.ACTION_INSERT.equals(mAction)) { 305825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (mListener != null) mListener.setTitleTo(R.string.editContact_title_insert); 306825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann 3072013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann final Account account = mIntentExtras == null ? null : 3082013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT); 3092013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann 3102013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann if (account != null) { 3112013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // Account specified in Intent 31240bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(account); 3132013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } else { 3142013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann // No Account specified. Let the user choose 31540bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov // Load Accounts async so that we can present them 31640bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov selectAccountAndCreateContact(); 3172013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann } 318a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else if (ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(mAction)) { 319a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov // do nothing 320825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } else throw new IllegalArgumentException("Unknown Action String " + mAction + 321825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT); 322825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann } 323222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 324222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 325e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 326e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onStart() { 327e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener); 328e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov super.onStart(); 329e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 330e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 3311015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov public void load(String action, Uri lookupUri, Bundle intentExtras) { 332f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mAction = action; 333b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = lookupUri; 334f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mIntentExtras = intentExtras; 3357d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov mAutoAddToDefaultGroup = mIntentExtras != null 3367d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY); 337f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 338f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 339f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void setListener(Listener value) { 340f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mListener = value; 341cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 342cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 343cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann @Override 344f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onCreate(Bundle savedState) { 345d364314c460152db7089b304beec81b3675893baDmitri Plotnikov if (savedState != null) { 346d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // Restore mUri before calling super.onCreate so that onInitializeLoaders 347d364314c460152db7089b304beec81b3675893baDmitri Plotnikov // would already have a uri and an action to work with 348b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri = savedState.getParcelable(KEY_URI); 349d364314c460152db7089b304beec81b3675893baDmitri Plotnikov mAction = savedState.getString(KEY_ACTION); 350d364314c460152db7089b304beec81b3675893baDmitri Plotnikov } 351d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 352f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onCreate(savedState); 353f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 354f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (savedState == null) { 355f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // If savedState is non-null, onRestoreInstanceState() will restore the generator. 356f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = new ViewIdGenerator(); 357f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 358825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Read state from savedState. No loading involved here 359ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = savedState.<EntityDeltaList> getParcelable(KEY_EDIT_STATE); 360f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mRawContactIdRequestingPhoto = savedState.getLong( 361f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann KEY_RAW_CONTACT_ID_REQUESTING_PHOTO); 362f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR); 363f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String fileName = savedState.getString(KEY_CURRENT_PHOTO_FILE); 364f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (fileName != null) { 365f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mCurrentPhotoFile = new File(fileName); 366cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 367f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN); 3689302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = savedState.getLong(KEY_SHOW_JOIN_SUGGESTIONS); 36902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEnabled = savedState.getBoolean(KEY_ENABLED); 370ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov mStatus = savedState.getInt(KEY_STATUS); 371cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 372cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 373cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 374bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann public void setData(ContactLoader.Result data) { 375d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann // If we have already loaded data, we do not want to change it here to not confuse the user 376d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann if (mState != null) { 377d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann Log.v(TAG, "Ignoring background change. This will have to be rebased later"); 378d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann return; 379d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann } 380d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann 381fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov // See if this edit operation needs to be redirected to a custom editor 382fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ArrayList<Entity> entities = data.getEntities(); 383fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (entities.size() == 1) { 384fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Entity entity = entities.get(0); 385fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentValues entityValues = entity.getEntityValues(); 386fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE); 387a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType(type); 388fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (accountType.getEditContactActivityClassName() != null) { 389fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 390fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov String name = entityValues.getAsString(RawContacts.ACCOUNT_NAME); 391fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID); 392fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(new Account(name, type), 393fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), 394fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mIntentExtras, true); 395fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 396fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov return; 397fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 398fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 399fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 400fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov bindEditorsForExistingContact(data); 401fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 402fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 403fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov @Override 404fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov public void onExternalEditorRequest(Account account, Uri uri) { 405fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomEditContactActivityRequested(account, uri, null, false); 406fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 407fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 408fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov private void bindEditorsForExistingContact(ContactLoader.Result data) { 40902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov setEnabled(true); 41002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 411a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mState = EntityDeltaList.fromIterator(data.getEntities().iterator()); 4121ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov setIntentExtras(mIntentExtras); 4131ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov mIntentExtras = null; 414e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikov 4151ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov bindEditors(); 4161ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 4171ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov 4181ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov /** 4191ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov * Merges extras from the intent. 4201ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov */ 4211ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov public void setIntentExtras(Bundle extras) { 4221ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov if (extras == null || extras.size() == 0) { 4231ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov return; 424bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann } 425916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 426a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 4271ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov for (EntityDelta state : mState) { 4281ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov final String accountType = state.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 429b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType type = accountTypes.getAccountType(accountType); 43069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (!type.readOnly) { 4311ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov // Apply extras to the first writable raw contact only 43269f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.parseExtras(mContext, type, state, extras); 4331ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov break; 4341ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 4351ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov } 436f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 437cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 43840bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov private void selectAccountAndCreateContact() { 439a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final ArrayList<Account> accounts = 440a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov AccountTypeManager.getInstance(mContext).getAccounts(true); 441f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // No Accounts available. Create a phone-local contact. 442f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (accounts.isEmpty()) { 44340bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(null); 444f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; // Don't show a dialog. 445f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 446cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 447f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // In the common case of a single account being writable, auto-select 448f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // it without showing a dialog. 449f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (accounts.size() == 1) { 45040bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(accounts.get(0)); 451f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; // Don't show a dialog. 452f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 453f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 45440bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov final SelectAccountDialogFragment dialog = new SelectAccountDialogFragment(); 4554a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.setTargetFragment(this, 0); 4564a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.show(getFragmentManager(), SelectAccountDialogFragment.TAG); 457cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 458cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 459cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 460f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param account may be null to signal a device-local contact should 461f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * be created. 462cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 46340bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov private void createContact(Account account) { 464a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 465b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType accountType = 466b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov accountTypes.getAccountType(account != null ? account.type : null); 467fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 468b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (accountType.getCreateContactActivityClassName() != null) { 469fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov if (mListener != null) { 470fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov mListener.onCustomCreateContactActivityRequested(account, mIntentExtras); 471fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 472fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 473b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov bindEditorsForNewContact(account, accountType); 474fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 475fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } 476fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 47769f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov private void bindEditorsForNewContact(Account account, final AccountType accountType) { 478a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov mStatus = Status.EDITING; 479a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 480f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ContentValues values = new ContentValues(); 481f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (account != null) { 482f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.put(RawContacts.ACCOUNT_NAME, account.name); 483f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.put(RawContacts.ACCOUNT_TYPE, account.type); 484f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 485f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_NAME); 486f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann values.putNull(RawContacts.ACCOUNT_TYPE); 487cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 488cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 489f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Parse any values from incoming intent 490f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values)); 49169f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.parseExtras(mContext, accountType, insert, mIntentExtras); 492f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 49369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov // Ensure we have some default fields (if the account type does not support a field, 494362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmann // ensureKind will not add it, so it is safe to add e.g. Event) 49569f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, Phone.CONTENT_ITEM_TYPE); 49669f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, Email.CONTENT_ITEM_TYPE); 49769f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, Note.CONTENT_ITEM_TYPE); 49869f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, Organization.CONTENT_ITEM_TYPE); 49969f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, Event.CONTENT_ITEM_TYPE); 50069f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, Website.CONTENT_ITEM_TYPE); 50169f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov EntityModifier.ensureKindExists(insert, accountType, StructuredPostal.CONTENT_ITEM_TYPE); 502f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 503f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mState == null) { 504f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Create state if none exists yet 505ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann mState = EntityDeltaList.fromSingle(insert); 506f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 507f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add contact onto end of existing state 508f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mState.add(insert); 509cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 510f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 511f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann bindEditors(); 512cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 513cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 514f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void bindEditors() { 515f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Sort the editors 516f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Collections.sort(mState, mComparator); 517cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 518f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Remove any existing editors and rebuild any visible 519f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.removeAllViews(); 520cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 521f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 522f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Context.LAYOUT_INFLATER_SERVICE); 523a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 524f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int size = mState.size(); 525f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann for (int i = 0; i < size; i++) { 526f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // TODO ensure proper ordering of entities in the list 527f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final EntityDelta entity = mState.get(i); 528f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final ValuesDelta values = entity.getValues(); 529f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!values.isVisible()) continue; 530f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 531f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 532b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType type = accountTypes.getAccountType(accountType); 533f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long rawContactId = values.getAsLong(RawContacts._ID); 534f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 53572af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor; 53669f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (type.isExternal()) { 537fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov editor = (BaseRawContactEditorView) inflater.inflate( 538fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov R.layout.external_raw_contact_editor_view, mContent, false); 539fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov ((ExternalRawContactEditorView) editor).setListener(this); 540fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov } else { 541f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann editor = (BaseRawContactEditorView) 542f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann inflater.inflate(R.layout.raw_contact_editor_view, mContent, false); 543cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 54402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov editor.setEnabled(mEnabled); 545cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 546f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.addView(editor); 5477d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 54869f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov editor.setState(entity, type, mViewIdGenerator); 549f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 5509442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann editor.getPhotoEditor().setEditorListener( 55169f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov new PhotoEditorListener(editor, type.readOnly)); 55272af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (editor instanceof RawContactEditorView) { 55372af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final RawContactEditorView rawContactEditor = (RawContactEditorView) editor; 554392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor(); 555f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov nameEditor.setEditorListener(new EditorListener() { 556f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 557f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 558f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onRequest(int request) { 55941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov onContactNameChange(request, rawContactEditor, nameEditor); 560f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 561f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 562f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 5634a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann public void onDeleted(Editor removedEditor) { 564f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 565f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov }); 566f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 5677d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup); 5687d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov 5699302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactId == mAggregationSuggestionsRawContactId) { 570f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov acquireAggregationSuggestions(rawContactEditor); 571f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 572f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 573cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 574f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 575e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 576e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 577f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Show editor now that we've loaded state 578f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContent.setVisibility(View.VISIBLE); 579a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 580a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann // Refresh Action Bar as the visibility of the join command 581825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // Activity can be null if we have been detached from the Activity 582825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann final Activity activity = getActivity(); 583825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann if (activity != null) activity.invalidateOptionsMenu(); 584cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 585cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 586e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private void bindGroupMetaData() { 587e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov if (mGroupMetaData == null) { 588e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov return; 589e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 590e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 591e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov int editorCount = mContent.getChildCount(); 592e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov for (int i = 0; i < editorCount; i++) { 59372af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann BaseRawContactEditorView editor = (BaseRawContactEditorView) mContent.getChildAt(i); 594e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov editor.setGroupMetaData(mGroupMetaData); 595e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 596e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 597e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 598b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 599eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { 600f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann inflater.inflate(R.menu.edit, menu); 601cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 602cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 603b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 604eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn public void onPrepareOptionsMenu(Menu menu) { 605f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann menu.findItem(R.id.menu_split).setVisible(mState != null && mState.size() > 1); 60602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int size = menu.size(); 60702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < size; i++) { 60802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov menu.getItem(i).setEnabled(mEnabled); 60902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 610cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 611cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 612b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann @Override 613cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public boolean onOptionsItemSelected(MenuItem item) { 614cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann switch (item.getItemId()) { 615f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_done: 6169df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.CLOSE); 617f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_discard: 618d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return revert(); 619f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_delete: 620f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doDeleteAction(); 621f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_split: 622f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doSplitContactAction(); 623f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann case R.id.menu_join: 624f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return doJoinContactAction(); 625f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 626f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 627f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 628cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 629f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 630f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Delete the entire contact currently being edited, which usually asks for 631f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * user confirmation before continuing. 632f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 633f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doDeleteAction() { 634f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) 635f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 636cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 637b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann // TODO: Make sure Insert turns into Edit if/once it is autosaved 638b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann if (Intent.ACTION_INSERT.equals(mAction)) { 639b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann if (mListener != null) mListener.onReverted(); 640cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } else { 641b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann if (mListener != null) mListener.onDeleteRequested(mLookupUri); 642cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 643f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 644f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 645f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 646f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doSplitContactAction() { 647f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!hasValidState()) return false; 648f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 649a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann final SplitContactConfirmationDialogFragment dialog = 6504a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann new SplitContactConfirmationDialogFragment(); 6514a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.setTargetFragment(this, 0); 6524a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG); 653f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 654f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 655f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 656f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean doJoinContactAction() { 6574c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov if (!hasValidState()) { 6584c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov return false; 6594c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 6604c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 6614c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // If we just started creating a new contact and haven't added any data, it's too 6624c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov // early to do a join 663a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 664a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (mState.size() == 1 && mState.get(0).isContactInsert() 665a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov && !EntityModifier.hasChanges(mState, accountTypes)) { 666a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(getActivity(), R.string.toast_join_with_empty_contact, 667a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.LENGTH_LONG).show(); 668a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov return true; 6694c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov } 6704c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov 6719df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov return save(SaveMode.JOIN); 672f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 673f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 674f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 675f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for picking a photo from Gallery, cropping it and returning the bitmap. 676f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 677f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getPhotoPickIntent() { 678f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); 679f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setType("image/*"); 680f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("crop", "true"); 681f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectX", 1); 682f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectY", 1); 683f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputX", ICON_SIZE); 684f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputY", ICON_SIZE); 685f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("return-data", true); 686f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 687f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 688f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 690f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Check if our internal {@link #mState} is valid, usually checked before 691f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * performing user actions. 692f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 693f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private boolean hasValidState() { 694f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return mState != null && mState.size() > 0; 695f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 696f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 697f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 698f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Create a file name for the icon photo using current time. 699f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 700f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private String getPhotoFileName() { 701f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Date date = new Date(System.currentTimeMillis()); 702f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("'IMG'_yyyyMMdd_HHmmss"); 703f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return dateFormat.format(date) + ".jpg"; 704f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 705f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 706f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 707f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for capturing a photo and storing it in a temporary file. 708f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 709f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getTakePickIntent(File f) { 710f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE, null); 711f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); 712f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 713f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 714f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 715f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 716f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Sends a newly acquired photo to Gallery for cropping 717f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 718f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann protected void doCropPhoto(File f) { 719f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann try { 720f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Add the image to the media store 721f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann MediaScannerConnection.scanFile( 722f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext, 723f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[] { f.getAbsolutePath() }, 724f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann new String[] { null }, 725f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann null); 726f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 727f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Launch gallery to crop the photo 728f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = getCropImageIntent(Uri.fromFile(f)); 729f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.SUB_ACTIVITY; 730a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_PHOTO_PICKED_WITH_DATA); 731f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } catch (Exception e) { 732f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Log.e(TAG, "Cannot crop image", e); 733f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show(); 734cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 735cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 736cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann 737f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 738f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Constructs an intent for image cropping. 739f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 740f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public static Intent getCropImageIntent(Uri photoUri) { 741f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Intent intent = new Intent("com.android.camera.action.CROP"); 742f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.setDataAndType(photoUri, "image/*"); 743f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("crop", "true"); 744f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectX", 1); 745f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("aspectY", 1); 746f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputX", ICON_SIZE); 747f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("outputY", ICON_SIZE); 748f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra("return-data", true); 749f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return intent; 750f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 751f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 752f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 753f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Saves or creates the contact based on the mode, and if successful 754f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * finishes the activity. 755f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 7569df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov public boolean save(int saveMode) { 757a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 758f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return false; 759f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 760f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 7618c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov // If we are about to close the editor - there is no need to refresh the data 762a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.SPLIT) { 7639d2bcfb40d0ee107886eb99eba13a840e944ba43Dianne Hackborn getLoaderManager().destroyLoader(LOADER_DATA); 7648c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov } 7658c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov 766825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.SAVING; 7676cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 768a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 769a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (!EntityModifier.hasChanges(mState, accountTypes)) { 770a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov onSaveCompleted(false, saveMode, mLookupUri); 7716cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov return true; 7726cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov } 7736cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov 774a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov setEnabled(false); 775f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 776a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Intent intent = ContactSaveService.createSaveContactIntent(getActivity(), mState, 777a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov SAVE_MODE_EXTRA_KEY, saveMode, getActivity().getClass(), 778a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov ContactEditorActivity.ACTION_SAVE_COMPLETED); 779a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov getActivity().startService(intent); 780f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return true; 781f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 782f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 783d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static class CancelEditDialogFragment extends DialogFragment { 784d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 785d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public static void show(ContactEditorFragment fragment) { 786d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment dialog = new CancelEditDialogFragment(); 787d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.setTargetFragment(fragment, 0); 788d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov dialog.show(fragment.getFragmentManager(), "cancelEditor"); 789d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 790d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 791d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 792d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 793d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov AlertDialog dialog = new AlertDialog.Builder(getActivity()) 7944292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 795d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setTitle(R.string.cancel_confirmation_dialog_title) 796d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setMessage(R.string.cancel_confirmation_dialog_message) 797d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setPositiveButton(R.string.discard, 798d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov new DialogInterface.OnClickListener() { 799d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov @Override 800d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 801d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ((ContactEditorFragment)getTargetFragment()).doRevertAction(); 802d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 803d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 804d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov ) 805d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .setNegativeButton(android.R.string.cancel, null) 806d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov .create(); 807d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return dialog; 808d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 809d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 810d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 811d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private boolean revert() { 812c863b0171f2a54a0ee71b34b33034aeea2464ccaDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 813c863b0171f2a54a0ee71b34b33034aeea2464ccaDmitri Plotnikov if (mState == null || !EntityModifier.hasChanges(mState, accountTypes)) { 814d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov doRevertAction(); 815d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } else { 816d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov CancelEditDialogFragment.show(this); 817d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 818d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov return true; 819d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov } 820d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov 821d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov private void doRevertAction() { 822825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // When this Fragment is closed we don't want it to auto-save 823825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 82422fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onReverted(); 825f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 826f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 8272b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov public void onJoinCompleted(Uri uri) { 828a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov onSaveCompleted(false, SaveMode.RELOAD, uri); 8292b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov } 8302b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov 831a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov public void onSaveCompleted(boolean hadChanges, int saveMode, Uri contactLookupUri) { 832a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov boolean success = contactLookupUri != null; 833a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Log.d(TAG, "onSaveCompleted(" + saveMode + ", " + contactLookupUri); 834a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (hadChanges) { 835a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (success) { 836a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov if (saveMode != SaveMode.JOIN) { 837a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); 838a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 839a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } else { 840a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); 841a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 842a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov } 843f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (saveMode) { 84415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.CLOSE: 8459df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov case SaveMode.HOME: 846f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent resultIntent; 847f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final int resultCode; 848f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (success && contactLookupUri != null) { 849b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann final String requestAuthority = 850b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann mLookupUri == null ? null : mLookupUri.getAuthority(); 851f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 852f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final String legacyAuthority = "contacts"; 853f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 854f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = new Intent(); 855f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (legacyAuthority.equals(requestAuthority)) { 856f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Build legacy Uri when requested by caller 857f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(Contacts.lookupContact( 858f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContext.getContentResolver(), contactLookupUri)); 859f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyContentUri = Uri.parse("content://contacts/people"); 860f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Uri legacyUri = ContentUris.withAppendedId( 861f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann legacyContentUri, contactId); 862f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(legacyUri); 863f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 864f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Otherwise pass back a lookup-style Uri 865f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent.setData(contactLookupUri); 866f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 867f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 868f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultCode = Activity.RESULT_OK; 869f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else { 870f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultCode = Activity.RESULT_CANCELED; 871f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann resultIntent = null; 872f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 873825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann // It is already saved, so prevent that it is saved again 874825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.CLOSING; 8759df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov if (mListener != null) mListener.onSaveFinished(resultCode, resultIntent, 8769df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov saveMode == SaveMode.HOME); 877f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 878a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 87915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.RELOAD: 880dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov case SaveMode.JOIN: 88115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann if (success && contactLookupUri != null) { 88215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If this was in INSERT, we are changing into an EDIT now. 88315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann // If it already was an EDIT, we are changing to the new Uri now 88415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann mState = null; 8851015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov load(Intent.ACTION_EDIT, contactLookupUri, null); 886825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.LOADING; 88715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener); 888dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov 889dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov // If it was a JOIN, we are now ready to bring up the join activity. 890dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov if (saveMode == SaveMode.JOIN) { 891dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov showJoinAggregateActivity(contactLookupUri); 892dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov } 89315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann } 89415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann break; 895a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov 89615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann case SaveMode.SPLIT: 897a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov mStatus = Status.CLOSING; 898a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann if (mListener != null) { 8998c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov mListener.onContactSplit(contactLookupUri); 900a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } else { 901a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann Log.d(TAG, "No listener registered, can not call onSplitFinished"); 902a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 903f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 904f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 905f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 906f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 907f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 908f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Shows a list of aggregates that can be joined into the currently viewed aggregate. 909f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * 910f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * @param contactLookupUri the fresh URI for the currently edited contact (after saving it) 911f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 912f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void showJoinAggregateActivity(Uri contactLookupUri) { 91373a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov if (contactLookupUri == null || !isAdded()) { 914f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return; 915f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 916f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 917f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann mContactIdForJoin = ContentUris.parseId(contactLookupUri); 918f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final Intent intent = new Intent(JoinContactActivity.JOIN_CONTACT); 919f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann intent.putExtra(JoinContactActivity.EXTRA_TARGET_CONTACT_ID, mContactIdForJoin); 920a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_JOIN); 921f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 922f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 923f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 924f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Performs aggregation with the contact selected by the user from suggestions or A-Z list. 925f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 926f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private void joinAggregate(final long contactId) { 9272b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin, 9282b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov contactId, isContactWritable(), 9292b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED); 9302b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov mContext.startService(intent); 931f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 932f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 933f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 934ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov * Returns true if there is at least one writable raw contact in the current contact. 935ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov */ 936ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov private boolean isContactWritable() { 937a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 938ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov int size = mState.size(); 939ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov for (int i = 0; i < size; i++) { 940ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov ValuesDelta values = mState.get(i).getValues(); 941ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 942b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType type = accountTypes.getAccountType(accountType); 94369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (!type.readOnly) { 944ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return true; 945ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 946ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 947ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov return false; 948ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov } 949ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov 950cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann public static interface Listener { 951cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann /** 95222fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was not found, so somehow close this fragment. This is raised after a contact 95322fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * is removed via Menu/Delete (unless it was a new contact) 954cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */ 95522fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onContactNotFound(); 956f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 957f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 9588c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov * Contact was split, so we can close now. 959a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * @param newLookupUri The lookup uri of the new contact that should be shown to the user. 960a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann * The editor tries best to chose the most natural contact here. 961f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 9628c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov void onContactSplit(Uri newLookupUri); 963f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 964f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 965f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User was presented with an account selection and couldn't decide. 966f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 96722fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onAccountSelectorAborted(); 968f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 969f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 970f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * User has tapped Revert, close the fragment now. 971f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 97222fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann void onReverted(); 973f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 974f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 975f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Set the Title (e.g. of the Activity) 976f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 977f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann void setTitleTo(int resourceId); 978f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 979f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 98022fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann * Contact was saved and the Fragment can now be closed safely. 981f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 9829df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov void onSaveFinished(int resultCode, Intent resultIntent, boolean navigateHome); 983b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann 984b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann /** 985b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann * User decided to delete the contact. 986b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann */ 987a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann void onDeleteRequested(Uri lookupUri); 988e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov 989e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov /** 990e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * User switched to editing a different contact (a suggestion from the 991e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov * aggregation engine). 992e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov */ 993e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov void onEditOtherContactRequested( 994e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov Uri contactLookupUri, ArrayList<ContentValues> contentValues); 995fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 996fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 997fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * Contact is being created for an external account that provides its own 998fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * new contact activity. 999fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 1000fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov void onCustomCreateContactActivityRequested(Account account, Bundle intentExtras); 1001fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov 1002fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov /** 1003fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * The edited raw contact belongs to an external account that provides 1004fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * its own edit activity. 1005fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * 1006fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * @param redirect indicates that the current editor should be closed 1007fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov * before the custom editor is shown. 1008fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov */ 1009fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov void onCustomEditContactActivityRequested(Account account, Uri rawContactUri, 1010fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov Bundle intentExtras, boolean redirect); 1011f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1012f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1013f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann private class EntityDeltaComparator implements Comparator<EntityDelta> { 1014f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1015f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann * Compare EntityDeltas for sorting the stack of editors. 1016f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann */ 10174a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann @Override 1018f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public int compare(EntityDelta one, EntityDelta two) { 1019f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check direct equality 1020f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (one.equals(two)) { 1021f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 0; 1022f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1023f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1024a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext); 1025b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov String accountType2 = one.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 1026b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType type1 = accountTypes.getAccountType(accountType2); 1027b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov accountType2 = two.getValues().getAsString(RawContacts.ACCOUNT_TYPE); 1028b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov final AccountType type2 = accountTypes.getAccountType(accountType2); 1029f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1030f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check read-only 1031b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (type1.readOnly && !type2.readOnly) { 1032f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1033b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov } else if (!type1.readOnly && type2.readOnly) { 1034f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1035f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1036f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1037f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account type 1038f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann boolean skipAccountTypeCheck = false; 1039b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount1 = type1 instanceof GoogleAccountType; 1040b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov boolean isGoogleAccount2 = type2 instanceof GoogleAccountType; 104169f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (isGoogleAccount1 && !isGoogleAccount2) { 1042f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 104369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (!isGoogleAccount1 && isGoogleAccount2) { 1044f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 104569f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov } else if (isGoogleAccount1 && isGoogleAccount2){ 1046f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann skipAccountTypeCheck = true; 1047f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1048f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1049f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann int value; 1050f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (!skipAccountTypeCheck) { 1051b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov if (type1.accountType == null) { 10522776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru return 1; 10532776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru } 1054b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov value = type1.accountType.compareTo(type2.accountType); 1055f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1056f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 1057f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1058f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1059f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1060f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Check account name 1061f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta oneValues = one.getValues(); 1062f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String oneAccount = oneValues.getAsString(RawContacts.ACCOUNT_NAME); 1063f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneAccount == null) oneAccount = ""; 1064f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann ValuesDelta twoValues = two.getValues(); 1065f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann String twoAccount = twoValues.getAsString(RawContacts.ACCOUNT_NAME); 1066f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (twoAccount == null) twoAccount = ""; 1067f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann value = oneAccount.compareTo(twoAccount); 1068f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (value != 0) { 1069f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return value; 1070f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1071f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1072f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Both are in the same account, fall back to contact ID 1073f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long oneId = oneValues.getAsLong(RawContacts._ID); 1074f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann Long twoId = twoValues.getAsLong(RawContacts._ID); 1075f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (oneId == null) { 1076f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return -1; 1077f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } else if (twoId == null) { 1078f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return 1; 1079f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1080f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1081f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann return (int)(oneId - twoId); 1082f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1083f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1084f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1085f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann /** 1086f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Returns the contact ID for the currently edited contact or 0 if the contact is new. 1087f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1088f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov protected long getContactId() { 1089f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov for (EntityDelta rawContact : mState) { 1090f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID); 1091f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (contactId != null) { 1092f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return contactId; 1093f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1094f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1095f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return 0; 1096f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1097f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 109841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 109972af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann private void onContactNameChange(int request, final RawContactEditorView rawContactEditor, 1100392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann TextFieldsEditorView nameEditor) { 110141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 110241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov switch (request) { 110341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov case EditorListener.EDITOR_FORM_CHANGED: 11040b85aed7ae694341ea226c88bf10c0e11ea990ceDmitri Plotnikov if (nameEditor.hasShortAndLongForms()) { 11050b85aed7ae694341ea226c88bf10c0e11ea990ceDmitri Plotnikov if (nameEditor.areOptionalFieldsVisible()) { 11060b85aed7ae694341ea226c88bf10c0e11ea990ceDmitri Plotnikov switchFromFullNameToStructuredName(nameEditor); 11070b85aed7ae694341ea226c88bf10c0e11ea990ceDmitri Plotnikov } else { 11080b85aed7ae694341ea226c88bf10c0e11ea990ceDmitri Plotnikov switchFromStructuredNameToFullName(nameEditor); 11090b85aed7ae694341ea226c88bf10c0e11ea990ceDmitri Plotnikov } 111041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 111141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov break; 111241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 111341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov case EditorListener.FIELD_CHANGED: 1114dbf3e60e3b3cfbd7114d319d6c9ea0cdab5997afDmitri Plotnikov if (nameEditor.hasShortAndLongForms()) { 1115dbf3e60e3b3cfbd7114d319d6c9ea0cdab5997afDmitri Plotnikov if (nameEditor.areOptionalFieldsVisible()) { 1116dbf3e60e3b3cfbd7114d319d6c9ea0cdab5997afDmitri Plotnikov eraseFullName(nameEditor.getValues()); 1117dbf3e60e3b3cfbd7114d319d6c9ea0cdab5997afDmitri Plotnikov } else { 1118dbf3e60e3b3cfbd7114d319d6c9ea0cdab5997afDmitri Plotnikov eraseStructuredName(nameEditor.getValues()); 1119dbf3e60e3b3cfbd7114d319d6c9ea0cdab5997afDmitri Plotnikov } 112041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 112141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov acquireAggregationSuggestions(rawContactEditor); 112241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov break; 112341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 112441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 112541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 1126392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void switchFromFullNameToStructuredName(LabeledEditorView nameEditor) { 112741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov ValuesDelta values = nameEditor.getValues(); 112841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 112941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov String displayName = values.getAsString(StructuredName.DISPLAY_NAME); 113041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov if (displayName == null) { 113141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov displayName = ""; 113241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 113341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 113441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov Uri uri = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name") 113541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov .appendQueryParameter(StructuredName.DISPLAY_NAME, displayName).build(); 113641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov Cursor cursor = getActivity().getContentResolver().query(uri, new String[]{ 113741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov StructuredName.PREFIX, 113841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov StructuredName.GIVEN_NAME, 113941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov StructuredName.MIDDLE_NAME, 114041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov StructuredName.FAMILY_NAME, 114141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov StructuredName.SUFFIX, 114241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov }, null, null, null); 114341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 114441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov try { 114541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov if (cursor.moveToFirst()) { 114641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov eraseFullName(values); 114741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.put(StructuredName.PREFIX, cursor.getString(0)); 114841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.put(StructuredName.GIVEN_NAME, cursor.getString(1)); 114941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.put(StructuredName.MIDDLE_NAME, cursor.getString(2)); 115041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.put(StructuredName.FAMILY_NAME, cursor.getString(3)); 115141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.put(StructuredName.SUFFIX, cursor.getString(4)); 115241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 115341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } finally { 115441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov cursor.close(); 115541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 115641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 115741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 1158392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void switchFromStructuredNameToFullName(LabeledEditorView nameEditor) { 115941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov ValuesDelta values = nameEditor.getValues(); 116041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 116141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov Uri.Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath( 116241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov "complete_name"); 116341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov appendQueryParameter(builder, values, StructuredName.PREFIX); 116441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov appendQueryParameter(builder, values, StructuredName.GIVEN_NAME); 116541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov appendQueryParameter(builder, values, StructuredName.MIDDLE_NAME); 116641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov appendQueryParameter(builder, values, StructuredName.FAMILY_NAME); 116741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov appendQueryParameter(builder, values, StructuredName.SUFFIX); 116841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov Uri uri = builder.build(); 116941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov Cursor cursor = getActivity().getContentResolver().query(uri, new String[]{ 117041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov StructuredName.DISPLAY_NAME, 117141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov }, null, null, null); 117241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 117341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov try { 117441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov if (cursor.moveToFirst()) { 117541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov eraseStructuredName(values); 117641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.put(StructuredName.DISPLAY_NAME, cursor.getString(0)); 117741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 117841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } finally { 117941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov cursor.close(); 118041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 118141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 118241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 118341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov private void eraseFullName(ValuesDelta values) { 118441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.putNull(StructuredName.DISPLAY_NAME); 118541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 118641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 118741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov private void eraseStructuredName(ValuesDelta values) { 118841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.putNull(StructuredName.PREFIX); 118941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.putNull(StructuredName.GIVEN_NAME); 119041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.putNull(StructuredName.MIDDLE_NAME); 119141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.putNull(StructuredName.FAMILY_NAME); 119241f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov values.putNull(StructuredName.SUFFIX); 119341f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 119441f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 119541f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov private void appendQueryParameter(Uri.Builder builder, ValuesDelta values, String field) { 119641f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov String value = values.getAsString(field); 119741f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov if (!TextUtils.isEmpty(value)) { 119841f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov builder.appendQueryParameter(field, value); 119941f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 120041f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov } 120141f026d52e0277e21236787b10f76129a8bc6fa4Dmitri Plotnikov 1202f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1203f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Triggers an asynchronous search for aggregation suggestions. 1204f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 120572af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann public void acquireAggregationSuggestions(RawContactEditorView rawContactEditor) { 12069302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov long rawContactId = rawContactEditor.getRawContactId(); 12079302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (mAggregationSuggestionsRawContactId != rawContactId 12089302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov && mAggregationSuggestionView != null) { 12099302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 12109302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = null; 12119302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionEngine.reset(); 12129302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 12139302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 12149302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionsRawContactId = rawContactId; 12159302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 1216f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (mAggregationSuggestionEngine == null) { 1217f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine = new AggregationSuggestionEngine(getActivity()); 1218f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.setListener(this); 1219f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.start(); 1220f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1221f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1222916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov mAggregationSuggestionEngine.setContactId(getContactId()); 1223916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov 1224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann LabeledEditorView nameEditor = rawContactEditor.getNameEditor(); 1225f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mAggregationSuggestionEngine.onNameChange(nameEditor.getValues()); 1226f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1227f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1228f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov @Override 1229f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov public void onAggregationSuggestionChange() { 1230a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (!isAdded() || mState == null || mStatus != Status.EDITING) { 123102cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov return; 123202cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov } 123302cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov 1234bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov RawContactEditorView rawContactView = 1235bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId); 12369302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (rawContactView == null) { 12379302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return; 12389302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1239f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 12409302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov ViewStub stub = (ViewStub)rawContactView.findViewById(R.id.aggregation_suggestion_stub); 1241f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (stub != null) { 1242f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov stub.inflate(); 1243f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1244f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 12459302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov // Only request the view on screen when it is first displayed 12469302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov boolean requestOnScreen = mAggregationSuggestionView == null; 12479302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView = rawContactView.findViewById(R.id.aggregation_suggestion); 1248f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1249f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov int count = mAggregationSuggestionEngine.getSuggestedContactCount(); 1250f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (count == 0) { 12519302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.GONE); 1252f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return; 1253f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1254f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 12559302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov List<Suggestion> suggestions = mAggregationSuggestionEngine.getSuggestions(); 12569302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 12579302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 12589302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov R.id.aggregation_suggestions); 1259f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov itemList.removeAllViews(); 1260f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1261f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov LayoutInflater inflater = getActivity().getLayoutInflater(); 1262f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1263f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov for (Suggestion suggestion : suggestions) { 1264f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov AggregationSuggestionView suggestionView = 1265f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov (AggregationSuggestionView) inflater.inflate( 1266f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov R.layout.aggregation_suggestions_item, null); 1267f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov suggestionView.setLayoutParams( 1268f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov new LinearLayout.LayoutParams( 1269f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 1270c0130cc28edccb21f6698066d90ce2120096eff2Dmitri Plotnikov suggestionView.setNewContact(mState.size() == 1 && mState.get(0).isContactInsert()); 1271bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov suggestionView.setListener(this); 12729302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov suggestionView.bindSuggestion(suggestion); 1273f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov itemList.addView(suggestionView); 1274f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 12759302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 1276bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov adjustAggregationSuggestionViewLayout(rawContactView); 1277a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov setAggregationSuggestionViewEnabled(mEnabled); 12789302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mAggregationSuggestionView.setVisibility(View.VISIBLE); 12799302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 12809302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestOnScreen) { 12819302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov mContent.postDelayed(new Runnable() { 12829302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 12839302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov @Override 12849302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov public void run() { 12859302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov requestAggregationSuggestionOnScreen(mAggregationSuggestionView); 12869302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 12879302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov }, AGGREGATION_SUGGESTION_SCROLL_DELAY); 12889302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 1289f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1290f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1291f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1292bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Adjusts the layout of the aggregation suggestion view so that it is placed directly 1293bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * underneath and have the same width as the last text editor of the contact name editor. 1294bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1295bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov private void adjustAggregationSuggestionViewLayout(RawContactEditorView rawContactView) { 1296392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann TextFieldsEditorView nameEditor = rawContactView.getNameEditor(); 1297bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Rect rect = new Rect(); 1298bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov nameEditor.acquireEditorBounds(rect); 1299bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov MarginLayoutParams layoutParams = 1300bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (MarginLayoutParams) mAggregationSuggestionView.getLayoutParams(); 1301bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov layoutParams.leftMargin = rect.left; 1302bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov layoutParams.width = rect.width(); 1303bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mAggregationSuggestionView.setLayoutParams(layoutParams); 1304bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1305bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1306bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1307bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onJoinAction(long contactId, List<Long> rawContactIdList) { 1308bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = new long[rawContactIdList.size()]; 1309bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov for (int i = 0; i < rawContactIds.length; i++) { 1310bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov rawContactIds[i] = rawContactIdList.get(i); 1311bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1312bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov JoinSuggestedContactDialogFragment dialog = 1313bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new JoinSuggestedContactDialogFragment(); 1314bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1315bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putLongArray("rawContactIds", rawContactIds); 1316bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1317bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 131874f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov try { 131974f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov dialog.show(getFragmentManager(), "join"); 132074f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } catch (Exception ex) { 132174f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov // No problem - the activity is no longer available to display the dialog 132274f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov } 1323bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1324bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1325bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class JoinSuggestedContactDialogFragment extends DialogFragment { 1326bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1327bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1328bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1329bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 13304292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1331bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setTitle(R.string.aggregation_suggestion_join_dialog_title) 1332bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_join_dialog_message) 1333bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1334bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1335bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1336bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1337bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1338bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov long rawContactIds[] = 1339bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getLongArray("rawContactIds"); 1340bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doJoinSuggestedContact(rawContactIds); 1341bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1342bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1343bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1344bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1345bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1346bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1347bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1348bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1349bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1350bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Joins the suggested contact (specified by the id's of constituent raw 1351bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * contacts), save all changes, and stay in the editor. 1352bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1353bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doJoinSuggestedContact(long[] rawContactIds) { 1354cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov if (!hasValidState() || mStatus != Status.EDITING) { 1355cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov return; 1356cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov } 1357cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov 1358bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mState.setJoinWithRawContacts(rawContactIds); 13599df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.RELOAD); 1360bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1361bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1362bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1363bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onEditAction(Uri contactLookupUri) { 1364bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov SuggestionEditConfirmationDialogFragment dialog = 1365bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new SuggestionEditConfirmationDialogFragment(); 1366bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Bundle args = new Bundle(); 1367bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov args.putParcelable("contactUri", contactLookupUri); 1368bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setArguments(args); 1369bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.setTargetFragment(this, 0); 1370bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov dialog.show(getFragmentManager(), "edit"); 1371bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1372bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1373bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public static class SuggestionEditConfirmationDialogFragment extends DialogFragment { 1374bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1375bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov @Override 1376bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public Dialog onCreateDialog(Bundle savedInstanceState) { 1377bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov return new AlertDialog.Builder(getActivity()) 13784292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov .setIconAttribute(android.R.attr.alertDialogIcon) 1379bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setTitle(R.string.aggregation_suggestion_edit_dialog_title) 1380bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setMessage(R.string.aggregation_suggestion_edit_dialog_message) 1381bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setPositiveButton(android.R.string.yes, 1382bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov new DialogInterface.OnClickListener() { 1383bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public void onClick(DialogInterface dialog, int whichButton) { 1384bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ContactEditorFragment targetFragment = 1385bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov (ContactEditorFragment) getTargetFragment(); 1386bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov Uri contactUri = 1387bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov getArguments().getParcelable("contactUri"); 1388bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov targetFragment.doEditSuggestedContact(contactUri); 1389bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1390bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1391bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov ) 1392bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .setNegativeButton(android.R.string.no, null) 1393bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov .create(); 1394bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1395bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1396bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1397bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1398bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * Abandons the currently edited contact and switches to editing the suggested 1399bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov * one, transferring all the data there 1400bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov */ 1401bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov protected void doEditSuggestedContact(Uri contactUri) { 1402bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov if (mListener != null) { 1403bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov mListener.onEditOtherContactRequested( 1404bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov contactUri, mState.get(0).getContentValues()); 1405bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1406bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov } 1407bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov 1408bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov /** 1409f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Scrolls the editor if necessary to reveal the aggregation suggestion that is 1410f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * shown below the name editor. Makes sure that the currently focused field 1411f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * remains visible. 1412f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1413f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private void requestAggregationSuggestionOnScreen(final View view) { 1414f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Rect rect = getRelativeBounds(mContent, view); 1415f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov View focused = mContent.findFocus(); 1416f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov if (focused != null) { 1417f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov rect.union(getRelativeBounds(mContent, focused)); 1418f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1419f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov mContent.requestRectangleOnScreen(rect); 1420f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1421f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1422a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov public void setAggregationSuggestionViewEnabled(boolean enabled) { 1423a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov if (mAggregationSuggestionView == null) { 1424a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov return; 1425a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1426a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1427a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById( 1428a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov R.id.aggregation_suggestions); 1429a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov int count = itemList.getChildCount(); 1430a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov for (int i = 0; i < count; i++) { 1431a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov itemList.getChildAt(i).setEnabled(enabled); 1432a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1433a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov } 1434a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov 1435f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov /** 1436f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov * Computes bounds of the supplied view relative to its ascendant. 1437f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov */ 1438f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov private Rect getRelativeBounds(View ascendant, View view) { 1439f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov Rect rect = new Rect(); 1440f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov rect.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); 1441f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1442f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov View parent = (View) view.getParent(); 1443f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov while (parent != ascendant) { 1444f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov rect.offset(parent.getLeft(), parent.getTop()); 1445f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov parent = (View) parent.getParent(); 1446f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1447f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov return rect; 1448f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov } 1449f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov 1450f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann @Override 1451f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onSaveInstanceState(Bundle outState) { 1452b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann outState.putParcelable(KEY_URI, mLookupUri); 1453d364314c460152db7089b304beec81b3675893baDmitri Plotnikov outState.putString(KEY_ACTION, mAction); 1454d364314c460152db7089b304beec81b3675893baDmitri Plotnikov 1455f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (hasValidState()) { 1456f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Store entities with modifications 1457f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_EDIT_STATE, mState); 1458f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1459f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1460f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto); 1461f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator); 1462f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (mCurrentPhotoFile != null) { 1463f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putString(KEY_CURRENT_PHOTO_FILE, mCurrentPhotoFile.toString()); 1464f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1465f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin); 14669302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov outState.putLong(KEY_SHOW_JOIN_SUGGESTIONS, mAggregationSuggestionsRawContactId); 146702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov outState.putBoolean(KEY_ENABLED, mEnabled); 1468ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov outState.putInt(KEY_STATUS, mStatus); 1469f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann super.onSaveInstanceState(outState); 1470f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1471f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1472d364314c460152db7089b304beec81b3675893baDmitri Plotnikov @Override 1473f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann public void onActivityResult(int requestCode, int resultCode, Intent data) { 1474f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov if (mStatus == Status.SUB_ACTIVITY) { 1475f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.EDITING; 1476f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov } 1477f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov 1478f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann // Ignore failed requests 1479f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (resultCode != Activity.RESULT_OK) return; 1480f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann switch (requestCode) { 1481a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_PHOTO_PICKED_WITH_DATA: { 1482c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann // As we are coming back to this view, the editor will be reloaded automatically, 1483c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann // which will cause the photo that is set here to disappear. To prevent this, 14844a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann // we remember to set a flag which is interpreted after loading. 14854a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann // This photo is set here already to reduce flickering. 1486c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mPhoto = data.getParcelableExtra("data"); 1487c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann setPhoto(mRawContactIdRequestingPhoto, mPhoto); 1488c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mRawContactIdRequestingPhotoAfterLoad = mRawContactIdRequestingPhoto; 1489c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mRawContactIdRequestingPhoto = -1; 1490f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann 1491f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1492f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1493a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_CAMERA_WITH_DATA: { 1494f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann doCropPhoto(mCurrentPhotoFile); 1495f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann break; 1496f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1497a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann case REQUEST_CODE_JOIN: { 1498f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann if (data != null) { 1499f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann final long contactId = ContentUris.parseId(data.getData()); 1500f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann joinAggregate(contactId); 1501f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 15024a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann break; 1503f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1504f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann } 1505cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann } 15069cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov 1507c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann /** 1508c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann * Sets the photo stored in mPhoto and writes it to the RawContact with the given id 1509c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann */ 1510c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann private void setPhoto(long rawContact, Bitmap photo) { 1511bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact); 15129302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (requestingEditor != null) { 15139302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov requestingEditor.setPhotoBitmap(photo); 15149302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } else { 15159302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov Log.w(TAG, "The contact that requested the photo is no longer present."); 15169302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 15179302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov } 15189302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov 15199302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov /** 15209302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov * Finds raw contact editor view for the given rawContactId. 15219302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov */ 1522bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov public BaseRawContactEditorView getRawContactEditorView(long rawContactId) { 1523c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann for (int i = 0; i < mContent.getChildCount(); i++) { 1524c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann final View childView = mContent.getChildAt(i); 152572af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 152672af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 15279302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov if (editor.getRawContactId() == rawContactId) { 15289302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return editor; 1529c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1530c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1531c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 15329302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov return null; 1533c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1534c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1535fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 1536fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann * Returns true if there is currently more than one photo on screen. 1537fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1538fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann private boolean hasMoreThanOnePhoto() { 1539fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int count = mContent.getChildCount(); 1540fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann int countWithPicture = 0; 1541fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann for (int i = 0; i < count; i++) { 1542fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann final View childView = mContent.getChildAt(i); 1543fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (childView instanceof BaseRawContactEditorView) { 1544fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 1545fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (editor.hasSetPhoto()) { 1546fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann countWithPicture++; 1547fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann if (countWithPicture > 1) return true; 1548fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1549fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1550fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1551fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 1552fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann return false; 15539cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov } 1554222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1555222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann /** 1556222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann * The listener for the data loader 1557222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann */ 1558222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener = 1559222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann new LoaderCallbacks<ContactLoader.Result>() { 1560222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1561222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) { 1562222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann mLoaderStartTime = SystemClock.elapsedRealtime(); 1563b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann return new ContactLoader(mContext, mLookupUri); 1564222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1565222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1566222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann @Override 1567222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) { 1568222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long loaderCurrentTime = SystemClock.elapsedRealtime(); 1569222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime)); 15705da9363bc4f2e04dc388579e1df979a5843e25e6Dmitri Plotnikov if (data == ContactLoader.Result.NOT_FOUND || data == ContactLoader.Result.ERROR) { 1571222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann // Item has been deleted 1572222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.i(TAG, "No contact found. Closing activity"); 157322fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann if (mListener != null) mListener.onContactNotFound(); 1574222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann return; 1575222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 1576222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann 1577825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann mStatus = Status.EDITING; 15786caccaeeed943db323be89853a108f422e670760Dmitri Plotnikov mLookupUri = data.getLookupUri(); 1579222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataStartTime = SystemClock.elapsedRealtime(); 1580222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann setData(data); 1581222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann final long setDataEndTime = SystemClock.elapsedRealtime(); 1582c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann 1583c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann // If we are coming back from the photo trimmer, this will be set. 1584c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann if (mRawContactIdRequestingPhotoAfterLoad != -1) { 1585c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann setPhoto(mRawContactIdRequestingPhotoAfterLoad, mPhoto); 1586c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mRawContactIdRequestingPhotoAfterLoad = -1; 1587c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann mPhoto = null; 1588c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann } 1589222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime)); 1590222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann } 15914ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 15924ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<ContactLoader.Result> loader) { 15934ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1594222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann }; 1595a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 1596e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov /** 1597e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov * The listener for the group meta data loader 1598e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov */ 1599e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener = 1600e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov new LoaderCallbacks<Cursor>() { 1601e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1602e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1603e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public CursorLoader onCreateLoader(int id, Bundle args) { 1604e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov return new GroupMetaDataLoader(mContext); 1605e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 1606e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1607e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov @Override 1608e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1609e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov mGroupMetaData = data; 1610e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov bindGroupMetaData(); 1611e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov } 16124ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn 16134ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 16144ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn } 1615e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov }; 1616e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov 1617a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann @Override 1618a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann public void onSplitContactConfirmed() { 1619a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann mState.markRawContactsForSplitting(); 16209df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov save(SaveMode.SPLIT); 1621a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1622a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 1623a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann /** 16249442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * Account was chosen in the selector. Create a RawContact for this account now 1625fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1626fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann @Override 162740bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov public void onAccountChosen(Account account) { 162840bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov createContact(account); 1629fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1630fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 1631fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann /** 16329442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * The account selector has been aborted. If we are in "New" mode, we have to close now 1633fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann */ 1634fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann @Override 16359442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onAccountSelectorCancelled() { 16369442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (!hasValidState() && mListener != null) { 16379442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mListener.onAccountSelectorAborted(); 16389442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16399442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16409442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 16419442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann private final class PhotoEditorListener 16429442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann implements EditorListener, PhotoActionPopup.Listener { 16439442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann private final BaseRawContactEditorView mEditor; 164469f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov private final boolean mAccountReadOnly; 16459442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 164669f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov private PhotoEditorListener(BaseRawContactEditorView editor, boolean accountReadOnly) { 16479442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mEditor = editor; 164869f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov mAccountReadOnly = accountReadOnly; 16499442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16509442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 16519442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 16529442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onRequest(int request) { 16539442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (!hasValidState()) return; 16549442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 16559442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (request == EditorListener.REQUEST_PICK_PHOTO) { 16569442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Determine mode 16579442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final int mode; 165869f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov if (mAccountReadOnly) { 16599442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (mEditor.hasSetPhoto() && hasMoreThanOnePhoto()) { 16609442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_READ_ONLY_ALLOW_PRIMARY; 16619442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16629442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Read-only and either no photo or the only photo ==> no options 16639442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann return; 16649442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16659442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16669442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (mEditor.hasSetPhoto()) { 16679442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (hasMoreThanOnePhoto()) { 16689442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_PHOTO_ALLOW_PRIMARY; 16699442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16709442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_PHOTO_DISALLOW_PRIMARY; 16719442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16729442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } else { 16739442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mode = PhotoActionPopup.MODE_NO_PHOTO; 16749442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1675fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 16769442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann PhotoActionPopup.createPopupMenu(mContext, mEditor.getPhotoEditor(), this, mode) 16779442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann .show(); 1678fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1679fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann } 1680fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann 16819442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 16829442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onDeleted(Editor removedEditor) { 16839442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1684a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 16859442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 16869442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * User has chosen to set the selected photo as the (super) primary photo 16879442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 16889442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 16899442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onUseAsPrimaryChosen() { 16909442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Set the IsSuperPrimary for each editor 16919442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann int count = mContent.getChildCount(); 16929442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann for (int i = 0; i < count; i++) { 16939442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final View childView = mContent.getChildAt(i); 16949442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann if (childView instanceof BaseRawContactEditorView) { 16959442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView; 16969442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final PhotoEditorView photoEditor = editor.getPhotoEditor(); 16979442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann photoEditor.setSuperPrimary(editor == mEditor); 16989442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 16999442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1700a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1701a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17029442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17039442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * User has chosen to remove a picture 17049442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17059442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17069442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onRemovePictureChose() { 17079442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mEditor.setPhotoBitmap(null); 1708a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann } 1709a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17109442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17119442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * Launches Camera to take a picture and store it in a file. 17129442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17139442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17149442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onTakePhotoChosen() { 17159442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 17169442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann try { 17179442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Launch camera to take photo for selected contact 17189442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann PHOTO_DIR.mkdirs(); 17199442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mCurrentPhotoFile = new File(PHOTO_DIR, getPhotoFileName()); 17209442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final Intent intent = getTakePickIntent(mCurrentPhotoFile); 17219442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann 1722f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.SUB_ACTIVITY; 17239442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_CAMERA_WITH_DATA); 17249442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } catch (ActivityNotFoundException e) { 17259442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, 17269442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.LENGTH_LONG).show(); 17279442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17289442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 1729a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann 17309442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann /** 17319442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann * Launches Gallery to pick a photo. 17329442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann */ 17339442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann @Override 17349442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann public void onPickFromGalleryChosen() { 17359442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann mRawContactIdRequestingPhoto = mEditor.getRawContactId(); 17369442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann try { 17379442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann // Launch picker to choose photo for selected contact 17389442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann final Intent intent = getPhotoPickIntent(); 1739f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov mStatus = Status.SUB_ACTIVITY; 17409442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann startActivityForResult(intent, REQUEST_CODE_PHOTO_PICKED_WITH_DATA); 17419442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } catch (ActivityNotFoundException e) { 17429442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.makeText(mContext, R.string.photoPickerNotFoundText, 17439442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann Toast.LENGTH_LONG).show(); 17449442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann } 17454a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 17464a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann } 17472ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey} 1748