ContactEditorFragment.java revision b697ed768fb817f94524f6c3992547665df331c4
13f990ba4e35a99078d831c041290e574a320caa5Walter Jang/*
23f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Copyright (C) 2015 The Android Open Source Project
33f990ba4e35a99078d831c041290e574a320caa5Walter Jang *
43f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Licensed under the Apache License, Version 2.0 (the "License");
53f990ba4e35a99078d831c041290e574a320caa5Walter Jang * you may not use this file except in compliance with the License.
63f990ba4e35a99078d831c041290e574a320caa5Walter Jang * You may obtain a copy of the License at
73f990ba4e35a99078d831c041290e574a320caa5Walter Jang *
83f990ba4e35a99078d831c041290e574a320caa5Walter Jang *      http://www.apache.org/licenses/LICENSE-2.0
93f990ba4e35a99078d831c041290e574a320caa5Walter Jang *
103f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Unless required by applicable law or agreed to in writing, software
113f990ba4e35a99078d831c041290e574a320caa5Walter Jang * distributed under the License is distributed on an "AS IS" BASIS,
123f990ba4e35a99078d831c041290e574a320caa5Walter Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f990ba4e35a99078d831c041290e574a320caa5Walter Jang * See the License for the specific language governing permissions and
143f990ba4e35a99078d831c041290e574a320caa5Walter Jang * limitations under the License
153f990ba4e35a99078d831c041290e574a320caa5Walter Jang */
163f990ba4e35a99078d831c041290e574a320caa5Walter Jang
173f990ba4e35a99078d831c041290e574a320caa5Walter Jangpackage com.android.contacts.editor;
183f990ba4e35a99078d831c041290e574a320caa5Walter Jang
197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.accounts.Account;
2049ed2033f83005f92c30068ae33c3138d75e1825Walter Jangimport android.app.Activity;
217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.app.Fragment;
227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.app.LoaderManager;
23e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskeyimport android.content.ContentResolver;
247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.ContentUris;
257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.ContentValues;
267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.Context;
277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.CursorLoader;
283f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.content.Intent;
297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.Loader;
307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.database.Cursor;
313efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.graphics.Bitmap;
323efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.net.Uri;
333f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.os.Bundle;
347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.os.SystemClock;
357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract;
367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Email;
377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Event;
387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Organization;
397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Phone;
407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.Intents;
437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.RawContacts;
44e394595987e288807b8c02c78d7d33e854f152b1Walter Jangimport android.text.TextUtils;
45cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jangimport android.util.Log;
463f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.view.LayoutInflater;
477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.view.Menu;
487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.view.MenuInflater;
49c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jangimport android.view.MenuItem;
503f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.view.View;
513f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.view.ViewGroup;
527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.widget.AdapterView;
537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.widget.BaseAdapter;
543f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.widget.LinearLayout;
557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.widget.ListPopupWindow;
5679658e14360a4ec75530a9dcae338f48c9d5f043Walter Jangimport android.widget.Toast;
5715646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Maiimport android.widget.Toolbar;
583f990ba4e35a99078d831c041290e574a320caa5Walter Jang
597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.ContactSaveService;
600a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.Experiments;
617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.GroupMetaDataLoader;
627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.R;
63a4adae163d83db9226b831f8c9705914e68b5cd1Gary Maiimport com.android.contacts.activities.ContactEditorAccountsChangedActivity;
64363af60ea23e5a3b945005712a16564ab69db18bGary Maiimport com.android.contacts.activities.ContactEditorActivity;
65363af60ea23e5a3b945005712a16564ab69db18bGary Maiimport com.android.contacts.activities.ContactEditorActivity.ContactEditor;
667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.activities.ContactSelectionActivity;
670a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
680a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.group.GroupUtil;
690a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.list.UiIntentActions;
7069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.logging.ScreenEvent.ScreenType;
7169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.AccountTypeManager;
7269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.Contact;
7369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ContactLoader;
7469c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContact;
7569c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactDelta;
7669c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactDeltaList;
7769c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactModifier;
7869c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ValuesDelta;
794bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport com.android.contacts.model.account.AccountInfo;
8069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountType;
8169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountWithDataSet;
824bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport com.android.contacts.model.account.AccountsLoader;
8369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.preference.ContactsPreferences;
84e48746654178e9448819f86b3129fd32f539b3c9Gary Maiimport com.android.contacts.quickcontact.InvisibleContactUtil;
857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.quickcontact.QuickContactActivity;
860a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.ContactDisplayUtils;
877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.util.ContactPhotoUtils;
880a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.ImplicitIntentsUtil;
890a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.MaterialColorMapUtils;
907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.util.UiClosables;
91a4adae163d83db9226b831f8c9705914e68b5cd1Gary Maiimport com.android.contactsbind.HelpUtils;
92581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jangimport com.android.contactsbind.ObjectFactory;
93581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jangimport com.android.contactsbind.experiments.Flags;
947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.google.common.collect.ImmutableList;
967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.google.common.collect.Lists;
977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
983efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport java.io.FileNotFoundException;
9931a74ad969b650eb733e536569254ed3978c4f54Walter Jangimport java.util.ArrayList;
1004bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport java.util.Collections;
1017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.HashSet;
1027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.Iterator;
1037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.List;
1047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.Set;
1053efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1063f990ba4e35a99078d831c041290e574a320caa5Walter Jang/**
1073f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Contact editor with only the most important fields displayed initially.
1083f990ba4e35a99078d831c041290e574a320caa5Walter Jang */
109363af60ea23e5a3b945005712a16564ab69db18bGary Maipublic class ContactEditorFragment extends Fragment implements
1107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        ContactEditor, SplitContactConfirmationDialogFragment.Listener,
1117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        JoinContactConfirmationDialogFragment.Listener,
1127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
1137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        CancelEditDialogFragment.Listener,
114363af60ea23e5a3b945005712a16564ab69db18bGary Mai        RawContactEditorView.Listener, PhotoEditorView.Listener {
1153f990ba4e35a99078d831c041290e574a320caa5Walter Jang
1167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    static final String TAG = "ContactEditor";
1177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final int LOADER_CONTACT = 1;
1197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final int LOADER_GROUPS = 2;
1204bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    private static final int LOADER_ACCOUNTS = 3;
1217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1223efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    private static final String KEY_PHOTO_RAW_CONTACT_ID = "photo_raw_contact_id";
12328a27279554af7b1e5ff664d3da97954c462a797Walter Jang    private static final String KEY_UPDATED_PHOTOS = "updated_photos";
1243efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final List<String> VALID_INTENT_ACTIONS = new ArrayList<String>() {{
1267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        add(Intent.ACTION_EDIT);
1277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        add(Intent.ACTION_INSERT);
128363af60ea23e5a3b945005712a16564ab69db18bGary Mai        add(ContactEditorActivity.ACTION_SAVE_COMPLETED);
1297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }};
1307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_ACTION = "action";
1327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_URI = "uri";
1337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_AUTO_ADD_TO_DEFAULT_GROUP = "autoAddToDefaultGroup";
1347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_DISABLE_DELETE_MENU_OPTION = "disableDeleteMenuOption";
1357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
1367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_MATERIAL_PALETTE = "materialPalette";
137c135a5d502130aee06ffcc11170513053396e9b0Gary Mai    private static final String KEY_ACCOUNT = "saveToAccount";
1387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
1397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_RAW_CONTACTS = "rawContacts";
1417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_EDIT_STATE = "state";
1437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_STATUS = "status";
1447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_HAS_NEW_CONTACT = "hasNewContact";
1467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_NEW_CONTACT_READY = "newContactDataReady";
1477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_IS_EDIT = "isEdit";
1497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
1507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_IS_USER_PROFILE = "isUserProfile";
1527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_ENABLED = "enabled";
1547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
1567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID =
1577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "aggregationSuggestionsRawContactId";
1587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
1607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin";
1617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
162698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private static final String KEY_READ_ONLY_DISPLAY_NAME_ID = "readOnlyDisplayNameId";
163698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private static final String KEY_COPY_READ_ONLY_DISPLAY_NAME = "copyReadOnlyDisplayName";
1647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected static final int REQUEST_CODE_JOIN = 0;
1667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
1677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * An intent extra that forces the editor to add the edited contact
1707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * to the default group (e.g. "My Contacts").
1717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
1737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
1757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION =
1777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "disableDeleteMenuOption";
1787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the photo palette primary color calculated by
181363af60ea23e5a3b945005712a16564ab69db18bGary Mai     * {@link com.android.contacts.quickcontact.QuickContactActivity} to the editor.
1827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR =
1847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "material_palette_primary_color";
1857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the photo palette secondary color calculated by
188363af60ea23e5a3b945005712a16564ab69db18bGary Mai     * {@link com.android.contacts.quickcontact.QuickContactActivity} to the editor.
1897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR =
1917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "material_palette_secondary_color";
1927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the ID of the photo to display on the editor.
1957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
196da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    // TODO: This can be cleaned up if we decide to not pass the photo id through
197da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    // QuickContactActivity.
1987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_PHOTO_ID = "photo_id";
1997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
201a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     * Intent key to pass the ID of the raw contact id that should be displayed in the full editor
202a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     * by itself.
203a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     */
204a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai    public static final String INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE =
205a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai            "raw_contact_id_to_display_alone";
206a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai
207a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai    /**
2087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent extra to specify a {@link ContactEditor.SaveMode}.
2097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
2117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent extra key for the contact ID to join the current contact to after saving.
2147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String JOIN_CONTACT_ID_EXTRA_KEY = "joinContactId";
2167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Callbacks for Activities that host contact editors Fragments.
2197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public interface Listener {
2217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was not found, so somehow close this fragment. This is raised after a contact
2247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * is removed via Menu/Delete
2257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onContactNotFound();
2277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was split, so we can close now.
2307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         *
2317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * @param newLookupUri The lookup uri of the new contact that should be shown to the user.
2327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         *                     The editor tries best to chose the most natural contact here.
2337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onContactSplit(Uri newLookupUri);
2357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * User has tapped Revert, close the fragment now.
2387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onReverted();
2407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was saved and the Fragment can now be closed safely.
2437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onSaveFinished(Intent resultIntent);
2457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
247678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai         * User switched to editing a different raw contact (a suggestion from the
2487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * aggregation engine).
2497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
250678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        void onEditOtherRawContactRequested(Uri contactLookupUri, long rawContactId,
2517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ArrayList<ContentValues> contentValues);
2527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * User has requested that contact be deleted.
2557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onDeleteRequested(Uri contactUri);
2577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
2587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Adapter for aggregation suggestions displayed in a PopupWindow when
2617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * editor fields change.
2627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final class AggregationSuggestionAdapter extends BaseAdapter {
2647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final LayoutInflater mLayoutInflater;
2657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final AggregationSuggestionView.Listener mListener;
2667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final List<AggregationSuggestionEngine.Suggestion> mSuggestions;
2677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
268678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        public AggregationSuggestionAdapter(Activity activity,
2697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) {
2707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mLayoutInflater = activity.getLayoutInflater();
2717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mListener = listener;
2727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mSuggestions = suggestions;
2737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public View getView(int position, View convertView, ViewGroup parent) {
2777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Suggestion suggestion = (Suggestion) getItem(position);
2787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final AggregationSuggestionView suggestionView =
2797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    (AggregationSuggestionView) mLayoutInflater.inflate(
2807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            R.layout.aggregation_suggestions_item, null);
2817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            suggestionView.setListener(mListener);
2827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            suggestionView.bindSuggestion(suggestion);
2837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return suggestionView;
2847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public long getItemId(int position) {
2887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return position;
2897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public Object getItem(int position) {
2937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return mSuggestions.get(position);
2947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public int getCount() {
2987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return mSuggestions.size();
2997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
3007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
3017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Context mContext;
3037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Listener mListener;
3047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Views
3077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected LinearLayout mContent;
3097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ListPopupWindow mAggregationSuggestionPopup;
3107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Parameters passed in on {@link #load}
3137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected String mAction;
3157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Uri mLookupUri;
3167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Bundle mIntentExtras;
3177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mAutoAddToDefaultGroup;
3187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mDisableDeleteMenuOption;
3197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewLocalProfile;
3207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected MaterialColorMapUtils.MaterialPalette mMaterialPalette;
3217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Helpers
3247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ContactEditorUtils mEditorUtils;
3267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected RawContactDeltaComparator mComparator;
3277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ViewIdGenerator mViewIdGenerator;
3287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private AggregationSuggestionEngine mAggregationSuggestionEngine;
3297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Loaded data
3327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Used to store existing contact data so it can be re-applied during a rebind call,
3347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // i.e. account switch.
3357b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai    protected Contact mContact;
3367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ImmutableList<RawContact> mRawContacts;
3377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Cursor mGroupMetaData;
3387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Editor state
3417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected RawContactDeltaList mState;
3437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected int mStatus;
3447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected long mRawContactIdToDisplayAlone = -1;
3457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether to show the new contact blank form and if it's corresponding delta is ready.
3477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mHasNewContact;
3487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected AccountWithDataSet mAccountWithDataSet;
3494bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    protected List<AccountInfo> mWritableAccounts = Collections.emptyList();
3507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewContactDataReady;
3517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewContactAccountChanged;
3527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether it's an edit of existing contact and if it's corresponding delta is ready.
3547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mIsEdit;
3557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mExistingContactDataReady;
3567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether we are editing the "me" profile
3587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mIsUserProfile;
3597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether editor views and options menu items should be enabled
3617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean mEnabled = true;
3627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
3647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private long mAggregationSuggestionsRawContactId;
3657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
3677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected long mContactIdForJoin;
3687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Used to pre-populate the editor with a display name when a user edits a read-only contact.
370698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    protected long mReadOnlyDisplayNameId;
371698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    protected boolean mCopyReadOnlyName;
3727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
3747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * The contact data loader listener.
3757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
3767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected final LoaderManager.LoaderCallbacks<Contact> mContactLoaderListener =
3777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            new LoaderManager.LoaderCallbacks<Contact>() {
3787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                protected long mLoaderStartTime;
3807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
3827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public Loader<Contact> onCreateLoader(int id, Bundle args) {
3837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mLoaderStartTime = SystemClock.elapsedRealtime();
384e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                    return new ContactLoader(mContext, mLookupUri,
385e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                            /* postViewNotification */ true,
386e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                            /* loadGroupMetaData */ true);
3877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
3887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
3907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoadFinished(Loader<Contact> loader, Contact contact) {
3917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long loaderCurrentTime = SystemClock.elapsedRealtime();
3927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
3937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (!contact.isLoaded()) {
3947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Item has been deleted. Close activity without saving again.
3957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        Log.i(TAG, "No contact found. Closing activity");
3967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mStatus = Status.CLOSING;
3977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        if (mListener != null) mListener.onContactNotFound();
3987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        return;
3997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
4007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mStatus = Status.EDITING;
4027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mLookupUri = contact.getLookupUri();
4037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long setDataStartTime = SystemClock.elapsedRealtime();
4047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    setState(contact);
4057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long setDataEndTime = SystemClock.elapsedRealtime();
4067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime - setDataStartTime));
4087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoaderReset(Loader<Contact> loader) {
4127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            };
4147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
4167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * The groups meta data loader listener.
4177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
4187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected final LoaderManager.LoaderCallbacks<Cursor> mGroupsLoaderListener =
4197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            new LoaderManager.LoaderCallbacks<Cursor>() {
4207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public CursorLoader onCreateLoader(int id, Bundle args) {
4235c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                    return new GroupMetaDataLoader(mContext, ContactsContract.Groups.CONTENT_URI,
4245c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                            GroupUtil.ALL_GROUPS_SELECTION);
4257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
4297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mGroupMetaData = data;
4307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    setGroupMetaData();
4317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoaderReset(Loader<Cursor> loader) {
4357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            };
4377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4384bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    protected LoaderManager.LoaderCallbacks<List<AccountInfo>> mAccountsLoaderListener =
4394bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott            new LoaderManager.LoaderCallbacks<List<AccountInfo>>() {
4404bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                @Override
4414bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
4424bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    return new AccountsLoader(getActivity(), AccountTypeManager.writableFilter());
4434bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                }
4444bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4454bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                @Override
4464bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                public void onLoadFinished(
4474bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                        Loader<List<AccountInfo>> loader, List<AccountInfo> data) {
4484bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    mWritableAccounts = data;
4494bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4504bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    final RawContactEditorView view = getContent();
4514bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    if (view == null) {
4524bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                        return;
4534bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    }
4544bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    view.setAccounts(data);
4554bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    if (mAccountWithDataSet == null && view.getCurrentRawContactDelta() == null) {
4564bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                        return;
4574bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    }
4584bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4594bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    final AccountWithDataSet account = mAccountWithDataSet != null
4604bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                            ? mAccountWithDataSet
4614bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                            : view.getCurrentRawContactDelta().getAccountWithDataSet();
4624bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4634bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    // The current account was removed
4644bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    if (!AccountInfo.contains(data, account) && !data.isEmpty()) {
4654bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                        if (isReadyToBindEditors()) {
4664bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                            onRebindEditorsForNewContact(getContent().getCurrentRawContactDelta(),
4674bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                                    account, data.get(0).getAccount());
4684bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                        } else {
4694bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                            mAccountWithDataSet = data.get(0).getAccount();
4704bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                        }
4714bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                    }
4724bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                }
4734bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4744bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                @Override
4754bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                public void onLoaderReset(Loader<List<AccountInfo>> loader) {
4764bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott                }
4774bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott            };
4784bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4794bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
4803efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    private long mPhotoRawContactId;
48128a27279554af7b1e5ff664d3da97954c462a797Walter Jang    private Bundle mUpdatedPhotos = new Bundle();
4823efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
4833efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
4847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public Context getContext() {
4857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return getActivity();
4867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
4877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
4897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onAttach(Activity activity) {
4907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onAttach(activity);
4917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mContext = activity;
492a7978d5bc3fcbe62a40e59e29aebea668385a98aMarcus Hagerott        mEditorUtils = ContactEditorUtils.create(mContext);
4937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mComparator = new RawContactDeltaComparator(mContext);
4947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
4957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
4973efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onCreate(Bundle savedState) {
4987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedState != null) {
4997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Restore mUri before calling super.onCreate so that onInitializeLoaders
5007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // would already have a uri and an action to work with
5017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAction = savedState.getString(KEY_ACTION);
5027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mLookupUri = savedState.getParcelable(KEY_URI);
5037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5053efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onCreate(savedState);
5063efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
5077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedState == null) {
5087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mViewIdGenerator = new ViewIdGenerator();
5097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // mState can still be null because it may not have have finished loading before
5117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // onSaveInstanceState was called.
5127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mState = new RawContactDeltaList();
5137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
5147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
5157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAutoAddToDefaultGroup = savedState.getBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP);
5177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mDisableDeleteMenuOption = savedState.getBoolean(KEY_DISABLE_DELETE_MENU_OPTION);
5187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
5197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mMaterialPalette = savedState.getParcelable(KEY_MATERIAL_PALETTE);
520c135a5d502130aee06ffcc11170513053396e9b0Gary Mai            mAccountWithDataSet = savedState.getParcelable(KEY_ACCOUNT);
5217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
5227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    KEY_RAW_CONTACTS));
5237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // NOTE: mGroupMetaData is not saved/restored
5247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Read state from savedState. No loading involved here
5267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE);
5277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = savedState.getInt(KEY_STATUS);
5287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT);
5307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY);
5317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mIsEdit = savedState.getBoolean(KEY_IS_EDIT);
5337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY);
5347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
5367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mEnabled = savedState.getBoolean(KEY_ENABLED);
5387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Aggregation PopupWindow
5407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionsRawContactId = savedState.getLong(
5417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID);
5427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Join Activity
5447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN);
5457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
546698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mReadOnlyDisplayNameId = savedState.getLong(KEY_READ_ONLY_DISPLAY_NAME_ID);
547698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mCopyReadOnlyName = savedState.getBoolean(KEY_COPY_READ_ONLY_DISPLAY_NAME, false);
5487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5493efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang            mPhotoRawContactId = savedState.getLong(KEY_PHOTO_RAW_CONTACT_ID);
55028a27279554af7b1e5ff664d3da97954c462a797Walter Jang            mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
5513efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        }
5523efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
5533efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
5543f990ba4e35a99078d831c041290e574a320caa5Walter Jang    @Override
5553f990ba4e35a99078d831c041290e574a320caa5Walter Jang    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
556ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang        setHasOptionsMenu(true);
557ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang
5583f990ba4e35a99078d831c041290e574a320caa5Walter Jang        final View view = inflater.inflate(
559363af60ea23e5a3b945005712a16564ab69db18bGary Mai                R.layout.contact_editor_fragment, container, false);
560f5dfea4a5c94382a632eae5c538881f7da726a50Walter Jang        mContent = (LinearLayout) view.findViewById(R.id.raw_contacts_editor_view);
5613f990ba4e35a99078d831c041290e574a320caa5Walter Jang        return view;
5623f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
5633f990ba4e35a99078d831c041290e574a320caa5Walter Jang
564ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang    @Override
5657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onActivityCreated(Bundle savedInstanceState) {
5667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onActivityCreated(savedInstanceState);
5677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        validateAction(mAction);
5697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5704bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott        if (!Intent.ACTION_EDIT.equals(mAction)) {
5714bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott            getLoaderManager().initLoader(LOADER_ACCOUNTS, null, mAccountsLoaderListener);
5724bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott        }
5734bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott
5747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty()) {
5757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // The delta list may not have finished loading before orientation change happens.
5767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // In this case, there will be a saved state but deltas will be missing.  Reload from
5777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // database.
5787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (Intent.ACTION_EDIT.equals(mAction)) {
5797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Either
5807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // 1) orientation change but load never finished.
5817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // 2) not an orientation change so data needs to be loaded for first time.
5827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                getLoaderManager().initLoader(LOADER_CONTACT, null, mContactLoaderListener);
5837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupsLoaderListener);
5847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
5867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Orientation change, we already have mState, it was loaded by onCreate
5877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            bindEditors();
5887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Handle initial actions only when existing state missing
5917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedInstanceState == null) {
5927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Account account = mIntentExtras == null ? null :
5937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
5947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final String dataSet = mIntentExtras == null ? null :
5957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
5967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (account != null) {
5977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAccountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet);
5987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (Intent.ACTION_EDIT.equals(mAction)) {
6017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mIsEdit = true;
6027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            } else if (Intent.ACTION_INSERT.equals(mAction)) {
6037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mHasNewContact = true;
6047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mAccountWithDataSet != null) {
6057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    createContact(mAccountWithDataSet);
606935b56aabd5ee1562df1d16324ce8e3f51005651Marcus Hagerott                } else if (mIntentExtras != null && mIntentExtras.getBoolean(
607363af60ea23e5a3b945005712a16564ab69db18bGary Mai                        ContactEditorActivity.EXTRA_SAVE_TO_DEVICE_FLAG, false)) {
608935b56aabd5ee1562df1d16324ce8e3f51005651Marcus Hagerott                    createContact(null);
6097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                } else {
6107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // No Account specified. Let the user choose
6117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // Load Accounts async so that we can present them
6127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    selectAccountAndCreateContact();
6137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
6147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
6157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
6197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Checks if the requested action is valid.
6207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
6217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param action The action to test.
6227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @throws IllegalArgumentException when the action is invalid.
6237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
6247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static void validateAction(String action) {
6257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (VALID_INTENT_ACTIONS.contains(action)) {
6267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
6277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        throw new IllegalArgumentException(
6297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                "Unknown action " + action + "; Supported actions: " + VALID_INTENT_ACTIONS);
6307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6333efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onSaveInstanceState(Bundle outState) {
6347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putString(KEY_ACTION, mAction);
6357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelable(KEY_URI, mLookupUri);
6367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP, mAutoAddToDefaultGroup);
6377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_DISABLE_DELETE_MENU_OPTION, mDisableDeleteMenuOption);
6387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile);
6397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mMaterialPalette != null) {
6407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            outState.putParcelable(KEY_MATERIAL_PALETTE, mMaterialPalette);
6417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
6437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelableArrayList(KEY_RAW_CONTACTS, mRawContacts == null ?
6457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                Lists.<RawContact>newArrayList() : Lists.newArrayList(mRawContacts));
6467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // NOTE: mGroupMetaData is not saved
6477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
64836ceb4235ed685a222af86076dcf160ba124a583Gary Mai        outState.putParcelable(KEY_EDIT_STATE, mState);
6497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putInt(KEY_STATUS, mStatus);
6507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact);
6517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady);
6527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_IS_EDIT, mIsEdit);
6537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady);
654c135a5d502130aee06ffcc11170513053396e9b0Gary Mai        outState.putParcelable(KEY_ACCOUNT, mAccountWithDataSet);
6557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
6567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_ENABLED, mEnabled);
6587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Aggregation PopupWindow
6607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putLong(KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID,
6617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAggregationSuggestionsRawContactId);
6627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Join Activity
6647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin);
6657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
666698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        outState.putLong(KEY_READ_ONLY_DISPLAY_NAME_ID, mReadOnlyDisplayNameId);
667698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        outState.putBoolean(KEY_COPY_READ_ONLY_DISPLAY_NAME, mCopyReadOnlyName);
6687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6693efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        outState.putLong(KEY_PHOTO_RAW_CONTACT_ID, mPhotoRawContactId);
67028a27279554af7b1e5ff664d3da97954c462a797Walter Jang        outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
6713efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onSaveInstanceState(outState);
6723efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
6733efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
6743efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
6757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onStop() {
6767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onStop();
6777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        UiClosables.closeQuietly(mAggregationSuggestionPopup);
6787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onDestroy() {
6827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onDestroy();
6837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine != null) {
6847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.quit();
6857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        switch (requestCode) {
6917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case REQUEST_CODE_JOIN: {
6927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Ignore failed requests
6937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (resultCode != Activity.RESULT_OK) return;
6947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (data != null) {
6957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long contactId = ContentUris.parseId(data.getData());
6967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (hasPendingChanges()) {
6977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Ask the user if they want to save changes before doing the join
6987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        JoinContactConfirmationDialogFragment.show(this, contactId);
6997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    } else {
7007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Do the join immediately
7017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        joinAggregate(contactId);
7027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
7037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
7047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
7057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
7067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case REQUEST_CODE_ACCOUNTS_CHANGED: {
7077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Bail if the account selector was not successful.
7087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (resultCode != Activity.RESULT_OK) {
7097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (mListener != null) {
7107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mListener.onReverted();
7117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
7127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    return;
7137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
7147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // If there's an account specified, use it.
7157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (data != null) {
7167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    AccountWithDataSet account = data.getParcelableExtra(
7177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            Intents.Insert.EXTRA_ACCOUNT);
7187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (account != null) {
7197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        createContact(account);
7207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        return;
7217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
7227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
7237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // If there isn't an account specified, then this is likely a phone-local
7247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // contact, so we should continue setting up the editor by automatically selecting
7257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // the most appropriate account.
7267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                createContact();
7277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
7287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
7297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
7337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Options menu
7347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
7357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
7387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        inflater.inflate(R.menu.edit_contact, menu);
7397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onPrepareOptionsMenu(Menu menu) {
7437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
7447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // because the custom action bar contains the "save" button now (not the overflow menu).
7457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
7467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem saveMenu = menu.findItem(R.id.menu_save);
7477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem splitMenu = menu.findItem(R.id.menu_split);
7487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem joinMenu = menu.findItem(R.id.menu_join);
7497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
7507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7515eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        // TODO: b/30771904, b/31827701, temporarily disable these items until we get them to work
7525eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        // on a raw contact level.
7535eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        joinMenu.setVisible(false);
7545eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        splitMenu.setVisible(false);
7555eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        deleteMenu.setVisible(false);
7567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Save menu is invisible when there's only one read only contact in the editor.
757d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai        saveMenu.setVisible(!isEditingReadOnlyRawContact());
7587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (saveMenu.isVisible()) {
7597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Since we're using a custom action layout we have to manually hook up the handler.
7607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            saveMenu.getActionView().setOnClickListener(new View.OnClickListener() {
7617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
7627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onClick(View v) {
7637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    onOptionsItemSelected(saveMenu);
7647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
7657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            });
7667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        int size = menu.size();
7697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        for (int i = 0; i < size; i++) {
7707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            menu.getItem(i).setEnabled(mEnabled);
7717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
775c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang    public boolean onOptionsItemSelected(MenuItem item) {
776c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang        if (item.getItemId() == android.R.id.home) {
777c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang            return revert();
778c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang        }
7797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
7817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
7827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // If we no longer are attached to a running activity want to
7837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // drain this event.
7847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
7857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
787b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        final int id = item.getItemId();
788b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        if (id == R.id.menu_save) {
789b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return save(SaveMode.CLOSE);
790b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_delete) {
791b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            if (mListener != null) mListener.onDeleteRequested(mLookupUri);
792b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return true;
793b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_split) {
794b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return doSplitContactAction();
795b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_join) {
796b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return doJoinContactAction();
797b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_help) {
798b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            HelpUtils.launchHelpAndFeedbackForContactScreen(getActivity());
799b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return true;
8007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return false;
8037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public boolean revert() {
8077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty() || !hasPendingChanges()) {
8087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onCancelEditConfirmed();
8097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
8107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            CancelEditDialogFragment.show(this);
8117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onCancelEditConfirmed() {
8177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // When this Fragment is closed we don't want it to auto-save
8187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.CLOSING;
8197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mListener != null) {
8207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mListener.onReverted();
8217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onSplitContactConfirmed(boolean hasPendingChanges) {
8267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty()) {
8277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // This may happen when this Fragment is recreated by the system during users
8287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // confirming the split action (and thus this method is called just before onCreate()),
8297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // for example.
8307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Log.e(TAG, "mState became null during the user's confirming split action. " +
8317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    "Cannot perform the save action.");
8327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
8337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasPendingChanges && mHasNewContact) {
8367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // If the user didn't add anything new, we don't want to split out the newly created
8377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // raw contact into a name-only contact so remove them.
8387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Iterator<RawContactDelta> iterator = mState.iterator();
8397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            while (iterator.hasNext()) {
8407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final RawContactDelta rawContactDelta = iterator.next();
8417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (rawContactDelta.getRawContactId() < 0) {
8427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    iterator.remove();
8437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
8447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
8457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.markRawContactsForSplitting();
8477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        save(SaveMode.SPLIT);
8487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
850b9065ddb28a2040cabda251891be2062b5260217Gary Mai    @Override
851b9065ddb28a2040cabda251891be2062b5260217Gary Mai    public void onSplitContactCanceled() {}
852b9065ddb28a2040cabda251891be2062b5260217Gary Mai
8537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean doSplitContactAction() {
8547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState()) return false;
8557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        SplitContactConfirmationDialogFragment.show(this, hasPendingChanges());
8577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean doJoinContactAction() {
8617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mLookupUri == null) {
8627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return false;
8637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we just started creating a new contact and haven't added any data, it's too
8667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // early to do a join
8677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.size() == 1 && mState.get(0).isContactInsert()
8687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                && !hasPendingChanges()) {
8697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Toast.makeText(mContext, R.string.toast_join_with_empty_contact,
8707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Toast.LENGTH_LONG).show();
8717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
8727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        showJoinAggregateActivity(mLookupUri);
8757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onJoinContactConfirmed(long joinContactId) {
8807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        doSaveAction(SaveMode.JOIN, joinContactId);
8817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
883c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang    @Override
8847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public boolean save(int saveMode) {
8857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mStatus != Status.EDITING) {
8867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return false;
8877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we are about to close the editor - there is no need to refresh the data
890363af60ea23e5a3b945005712a16564ab69db18bGary Mai        if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.EDITOR
8917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                || saveMode == SaveMode.SPLIT) {
8927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            getLoaderManager().destroyLoader(LOADER_CONTACT);
8937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.SAVING;
8967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasPendingChanges()) {
8987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mLookupUri == null && saveMode == SaveMode.RELOAD) {
8997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // We don't have anything to save and there isn't even an existing contact yet.
9007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Nothing to do, simply go back to editing mode
9017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.EDITING;
9027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return true;
9037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
9047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onSaveCompleted(/* hadChanges =*/ false, saveMode,
9057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    /* saveSucceeded =*/ mLookupUri != null, mLookupUri, /* joinContactId =*/ null);
9067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
9077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
9087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setEnabled(false);
9107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return doSaveAction(saveMode, /* joinContactId */ null);
9127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
9157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // State accessor methods
9167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
9177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Check if our internal {@link #mState} is valid, usually checked before
9207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * performing user actions.
9217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasValidState() {
9237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return mState.size() > 0;
9247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean isEditingUserProfile() {
9277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return mNewLocalProfile || mIsUserProfile;
9287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9315a00de39004d298de4daee3e183add5eff17102cGary Mai     * Whether the contact being edited is composed of read-only raw contacts
9327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * aggregated with a newly created writable raw contact.
9337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean isEditingReadOnlyRawContactWithNewContact() {
9355a00de39004d298de4daee3e183add5eff17102cGary Mai        return mHasNewContact && mState.size() > 1;
9367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
939d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai     * @return true if the single raw contact we're looking at is read-only.
940d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai     */
941d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    private boolean isEditingReadOnlyRawContact() {
942d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai        return hasValidState() && mRawContactIdToDisplayAlone > 0
943d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                && !mState.getByRawContactId(mRawContactIdToDisplayAlone)
944d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                        .getAccountType(AccountTypeManager.getInstance(mContext))
945d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                                .areContactsWritable();
946d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    }
947d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai
948d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    /**
9497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Return true if there are any edits to the current contact which need to
9507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * be saved.
9517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasPendingRawContactChanges(Set<String> excludedMimeTypes) {
9537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
9547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return RawContactModifier.hasChanges(mState, accountTypes, excludedMimeTypes);
9557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Determines if changes were made in the editor that need to be saved, while taking into
9597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * account that name changes are not real for read-only contacts.
9607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * See go/editing-read-only-contacts
9617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasPendingChanges() {
963698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (isEditingReadOnlyRawContactWithNewContact()) {
9647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // We created a new raw contact delta with a default display name.
9657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // We must test for pending changes while ignoring the default display name.
966698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final ValuesDelta beforeDelta = mState.getByRawContactId(mReadOnlyDisplayNameId)
967698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                    .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
968698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final ValuesDelta pendingDelta = mState
969698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                    .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
970698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (structuredNamesAreEqual(beforeDelta, pendingDelta)) {
9717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final Set<String> excludedMimeTypes = new HashSet<>();
9727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                excludedMimeTypes.add(StructuredName.CONTENT_ITEM_TYPE);
9737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return hasPendingRawContactChanges(excludedMimeTypes);
9747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
9757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
9767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
9777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return hasPendingRawContactChanges(/* excludedMimeTypes =*/ null);
9787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
981698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * Compares the two {@link ValuesDelta} to see if the structured name is changed. We made a copy
982698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * of a read only delta and now we want to check if the copied delta has changes.
983698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     *
984698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @param before original {@link ValuesDelta}
985698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @param after copied {@link ValuesDelta}
986698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @return true if the copied {@link ValuesDelta} has all the same values in the structured
987698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * name fields as the original.
988698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     */
989698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private boolean structuredNamesAreEqual(ValuesDelta before, ValuesDelta after) {
9905a00de39004d298de4daee3e183add5eff17102cGary Mai        if (before == after) return true;
991698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (before == null || after == null) return false;
992698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ContentValues original = before.getBefore();
993698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ContentValues pending = after.getAfter();
994698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (original != null && pending != null) {
995a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            final String beforeDisplayName = original.getAsString(StructuredName.DISPLAY_NAME);
996698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterDisplayName = pending.getAsString(StructuredName.DISPLAY_NAME);
997698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeDisplayName, afterDisplayName)) return false;
998698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
999698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforePrefix = original.getAsString(StructuredName.PREFIX);
1000698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterPrefix = pending.getAsString(StructuredName.PREFIX);
1001698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforePrefix, afterPrefix)) return false;
1002698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
1003698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeFirstName = original.getAsString(StructuredName.GIVEN_NAME);
1004698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterFirstName = pending.getAsString(StructuredName.GIVEN_NAME);
1005698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeFirstName, afterFirstName)) return false;
1006698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
1007698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeMiddleName = original.getAsString(StructuredName.MIDDLE_NAME);
1008698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterMiddleName = pending.getAsString(StructuredName.MIDDLE_NAME);
1009698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeMiddleName, afterMiddleName)) return false;
1010698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
1011698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeLastName = original.getAsString(StructuredName.FAMILY_NAME);
1012698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterLastName = pending.getAsString(StructuredName.FAMILY_NAME);
1013698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeLastName, afterLastName)) return false;
1014698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
1015698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeSuffix = original.getAsString(StructuredName.SUFFIX);
1016698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterSuffix = pending.getAsString(StructuredName.SUFFIX);
1017698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            return TextUtils.equals(beforeSuffix, afterSuffix);
1018698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1019698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        return false;
1020698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    }
1021698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
10227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Account creation
10247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void selectAccountAndCreateContact() {
10277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If this is a local profile, then skip the logic about showing the accounts changed
10287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // activity and create a phone-local contact.
10297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mNewLocalProfile) {
10307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(null);
10317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If there is no default account or the accounts have changed such that we need to
10357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // prompt the user again, then launch the account prompt.
10367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mEditorUtils.shouldShowAccountChangedNotification()) {
10377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
10387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Prevent a second instance from being started on rotates
10397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
10407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = Status.SUB_ACTIVITY;
10417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED);
10427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
10433107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            // Make sure the default account is automatically set if there is only one non-device
10443107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            // account.
10453107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            mEditorUtils.maybeUpdateDefaultAccount();
10467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Otherwise, there should be a default account. Then either create a local contact
10477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // (if default account is null) or create a contact with the specified account.
1048a7978d5bc3fcbe62a40e59e29aebea668385a98aMarcus Hagerott            AccountWithDataSet defaultAccount = mEditorUtils.getOnlyOrDefaultAccount();
10497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(defaultAccount);
10507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Create a contact by automatically selecting the first account. If there's no available
10557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * account, a device-local contact should be created.
10567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void createContact() {
10587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final List<AccountWithDataSet> accounts =
10597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                AccountTypeManager.getInstance(mContext).getAccounts(true);
10607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // No Accounts available. Create a phone-local contact.
10617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (accounts.isEmpty()) {
10627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(null);
10637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // We have an account switcher in "create-account" screen, so don't need to ask a user to
10677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // select an account here.
10687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        createContact(accounts.get(0));
10697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Shows account creation screen associated with a given account.
10737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
10747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param account may be null to signal a device-local contact should be created.
10757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void createContact(AccountWithDataSet account) {
10777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
10787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountType accountType = accountTypes.getAccountTypeForAccount(account);
10797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1080aebf3206766a05cce290245f09506adb789b6e37Gary Mai        setStateForNewContact(account, accountType, isEditingUserProfile());
10817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Data binding
10857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setState(Contact contact) {
10887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we have already loaded data, we do not want to change it here to not confuse the user
10897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!mState.isEmpty()) {
10907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Log.v(TAG, "Ignoring background change. This will have to be rebased later");
10917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10937b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai        mContact = contact;
10944ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai        mRawContacts = contact.getRawContacts();
10957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Check for writable raw contacts.  If there are none, then we need to create one so user
10977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // can edit.  For the user profile case, there is already an editable contact.
10987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
10997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = true;
1100698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mReadOnlyDisplayNameId = contact.getNameRawContactId();
1101698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mCopyReadOnlyName = true;
11027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // This is potentially an asynchronous call and will add deltas to list.
11037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            selectAccountAndCreateContact();
11047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = false;
11067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1108698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        setStateForExistingContact(contact.isUserProfile(), mRawContacts);
1109e48746654178e9448819f86b3129fd32f539b3c9Gary Mai        if (mAutoAddToDefaultGroup
1110e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                && InvisibleContactUtil.isInvisibleAndAddable(contact, getContext())) {
1111e48746654178e9448819f86b3129fd32f539b3c9Gary Mai            InvisibleContactUtil.markAddToDefaultGroup(contact, mState, getContext());
1112e48746654178e9448819f86b3129fd32f539b3c9Gary Mai        }
11137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for a newly created phone-local contact.
11177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
11197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            boolean isUserProfile) {
11207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setStateForNewContact(account, accountType, /* oldState =*/ null,
11217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                /* oldAccountType =*/ null, isUserProfile);
11227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for a newly created phone-local contact, migrating the state
11267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * specified by oldState and oldAccountType.
11277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
11297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactDelta oldState, AccountType oldAccountType, boolean isUserProfile) {
11307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.EDITING;
11317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.add(createNewRawContactDelta(account, accountType, oldState, oldAccountType));
11327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIsUserProfile = isUserProfile;
11337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mNewContactDataReady = true;
11347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        bindEditors();
11357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns a {@link RawContactDelta} for a new contact suitable for addition into
11397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * {@link #mState}.
11407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
11417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * If oldState and oldAccountType are specified, the state specified by those parameters
11427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * is migrated to the result {@link RawContactDelta}.
11437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private RawContactDelta createNewRawContactDelta(AccountWithDataSet account,
11457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            AccountType accountType, RawContactDelta oldState, AccountType oldAccountType) {
11467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContact rawContact = new RawContact();
11477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (account != null) {
11487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            rawContact.setAccount(account);
11497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            rawContact.setAccountToLocal();
11517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContactDelta result = new RawContactDelta(
11547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ValuesDelta.fromAfter(rawContact.getValues()));
11557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (oldState == null) {
11567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Parse any values from incoming intent
11577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactModifier.parseExtras(mContext, accountType, result, mIntentExtras);
11587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactModifier.migrateStateForNewContact(
11607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mContext, oldState, result, oldAccountType, accountType);
11617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Ensure we have some default fields (if the account type does not support a field,
11647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // ensureKind will not add it, so it is safe to add e.g. Event)
116562ec0b10c0ddc00053df39aeaed1f3316116e849Gary Mai        RawContactModifier.ensureKindExists(result, accountType, StructuredName.CONTENT_ITEM_TYPE);
11667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Phone.CONTENT_ITEM_TYPE);
11677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Email.CONTENT_ITEM_TYPE);
11687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Organization.CONTENT_ITEM_TYPE);
11697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Event.CONTENT_ITEM_TYPE);
11707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType,
11717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                StructuredPostal.CONTENT_ITEM_TYPE);
11727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Set the correct URI for saving the contact as a profile
11747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mNewLocalProfile) {
11757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            result.setProfileQueryUri();
11767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
11797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for an existing contact.
11837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1184698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private void setStateForExistingContact(boolean isUserProfile,
11857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            ImmutableList<RawContact> rawContacts) {
11867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setEnabled(true);
11877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.addAll(rawContacts.iterator());
11897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setIntentExtras(mIntentExtras);
11907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIntentExtras = null;
11917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // For user profile, change the contacts query URI
11937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIsUserProfile = isUserProfile;
11947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        boolean localProfileExists = false;
11957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mIsUserProfile) {
11977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            for (RawContactDelta rawContactDelta : mState) {
11987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // For profile contacts, we need a different query URI
11997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                rawContactDelta.setProfileQueryUri();
12007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Try to find a local profile contact
12017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (rawContactDelta.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) {
12027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    localProfileExists = true;
12037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
12047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
12057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Editor should always present a local profile for editing
12067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // TODO(wjang): Need to figure out when this case comes up.  We can't do this if we're
12077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // going to prune all but the one raw contact that we're trying to display by itself.
12087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (!localProfileExists && mRawContactIdToDisplayAlone <= 0) {
12097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mState.add(createLocalRawContactDelta());
12107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
12117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
12127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mExistingContactDataReady = true;
12137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        bindEditors();
12147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Set the enabled state of editors.
12187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
12197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setEnabled(boolean enabled) {
12207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mEnabled != enabled) {
12217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mEnabled = enabled;
12227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Enable/disable editors
12247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mContent != null) {
12257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                int count = mContent.getChildCount();
12267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                for (int i = 0; i < count; i++) {
12277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mContent.getChildAt(i).setEnabled(enabled);
12287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
12297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
12307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Maybe invalidate the options menu
12327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Activity activity = getActivity();
12337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (activity != null) activity.invalidateOptionsMenu();
12347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
12357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns a {@link RawContactDelta} for a local contact suitable for addition into
12397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * {@link #mState}.
12407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
12417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static RawContactDelta createLocalRawContactDelta() {
12427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContact rawContact = new RawContact();
12437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        rawContact.setAccountToLocal();
12447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContactDelta result = new RawContactDelta(
12467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ValuesDelta.fromAfter(rawContact.getValues()));
12477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        result.setProfileQueryUri();
12487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
12507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1252698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private void copyReadOnlyName() {
1253698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        // We should only ever be doing this if we're creating a new writable contact to attach to
1254698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        // a read only contact.
1255698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (!isEditingReadOnlyRawContactWithNewContact()) {
1256698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            return;
1257698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1258698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final int writableIndex = mState.indexOfFirstWritableRawContact(getContext());
1259698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final RawContactDelta writable = mState.get(writableIndex);
12607b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai        final RawContactDelta readOnly = mState.getByRawContactId(mContact.getNameRawContactId());
1261698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ValuesDelta writeNameDelta = writable
1262698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
1263698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ValuesDelta readNameDelta = readOnly
1264698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
1265698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        mCopyReadOnlyName = false;
1266860698b8d4542a55da5ec40032a361433b525aadGary Mai        if (writeNameDelta == null || readNameDelta == null) {
1267860698b8d4542a55da5ec40032a361433b525aadGary Mai            return;
1268860698b8d4542a55da5ec40032a361433b525aadGary Mai        }
1269860698b8d4542a55da5ec40032a361433b525aadGary Mai        writeNameDelta.copyStructuredNameFieldsFrom(readNameDelta);
1270698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    }
1271698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
12727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Bind editors using {@link #mState} and other members initialized from the loaded (or new)
12747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Contact.
12757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1276ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang    protected void bindEditors() {
1277cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (!isReadyToBindEditors()) {
1278cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return;
1279cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1280cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
1281d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Add input fields for the loaded Contact
1282363af60ea23e5a3b945005712a16564ab69db18bGary Mai        final RawContactEditorView editorView = getContent();
1283b6ca272f26b47ecef8fafe94326c4d553576c521Walter Jang        editorView.setListener(this);
1284698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (mCopyReadOnlyName) {
1285698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            copyReadOnlyName();
1286698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1287678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        editorView.setState(mState, mMaterialPalette, mViewIdGenerator,
12889a55237f705453caae1f8aa3576a9acd7596d5ecWalter Jang                mHasNewContact, mIsUserProfile, mAccountWithDataSet,
12895a00de39004d298de4daee3e183add5eff17102cGary Mai                mRawContactIdToDisplayAlone);
1290079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai        if (isEditingReadOnlyRawContact()) {
129115646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai            final Toolbar toolbar = getEditorActivity().getToolbar();
129215646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai            if (toolbar != null) {
129315646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai                toolbar.setTitle(R.string.contact_editor_title_read_only_contact);
1294d8f3da6a4ea4054bd47959db85657a7e01d28358Gary Mai                // Set activity title for Talkback
1295d8f3da6a4ea4054bd47959db85657a7e01d28358Gary Mai                getEditorActivity().setTitle(R.string.contact_editor_title_read_only_contact);
1296bd9ef3c60669d71543b3506d4959c1fe4be409dcJohn Shao                toolbar.setNavigationIcon(R.drawable.quantum_ic_arrow_back_vd_theme_24);
129715646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai                toolbar.setNavigationContentDescription(R.string.back_arrow_content_description);
1298bd9ef3c60669d71543b3506d4959c1fe4be409dcJohn Shao                toolbar.getNavigationIcon().setAutoMirrored(true);
1299079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai            }
1300079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai        }
1301cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
1302d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Set up the photo widget
130331a74ad969b650eb733e536569254ed3978c4f54Walter Jang        editorView.setPhotoListener(this);
13043efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        mPhotoRawContactId = editorView.getPhotoRawContactId();
130531a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // If there is an updated full resolution photo apply it now, this will be the case if
130631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // the user selects or takes a new photo, then rotates the device.
130731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Uri uri = (Uri) mUpdatedPhotos.get(String.valueOf(mPhotoRawContactId));
130831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (uri != null) {
130931a74ad969b650eb733e536569254ed3978c4f54Walter Jang            editorView.setFullSizePhoto(uri);
131041b3ea1c712f01164feb55455f1391564cb76deeWalter Jang        }
13113efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1312d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // The editor is ready now so make it visible
1313678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        editorView.setEnabled(mEnabled);
1314d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        editorView.setVisibility(View.VISIBLE);
1315d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang
1316d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Refresh the ActionBar as the visibility of the join command
1317d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Activity can be null if we have been detached from the Activity.
1318cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        invalidateOptionsMenu();
1319cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang    }
1320cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
13217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
13227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Invalidates the options menu if we are still associated with an Activity.
13237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
13247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void invalidateOptionsMenu() {
13257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
13267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (activity != null) {
13277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            activity.invalidateOptionsMenu();
13287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
13297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1331cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang    private boolean isReadyToBindEditors() {
1332cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mState.isEmpty()) {
1333cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1334cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "No data to bind editors");
1335cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1336cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1337cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1338cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mIsEdit && !mExistingContactDataReady) {
1339cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1340cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "Existing contact data is not ready to bind editors.");
1341cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1342cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1343cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1344cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mHasNewContact && !mNewContactDataReady) {
1345cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1346cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "New contact data is not ready to bind editors.");
1347cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1348cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1349cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1350cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        return true;
1351ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang    }
1352ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang
13537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
13547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Removes a current editor ({@link #mState}) and rebinds new editor for a new account.
13557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Some of old data are reused with new restriction enforced by the new account.
13567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
13577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param oldState Old data being edited.
13587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param oldAccount Old account associated with oldState.
13597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param newAccount New account to be used.
13607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
13617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void rebindEditorsForNewContact(
13627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactDelta oldState, AccountWithDataSet oldAccount,
13637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            AccountWithDataSet newAccount) {
13647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
13657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountType oldAccountType = accountTypes.getAccountTypeForAccount(oldAccount);
13667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountType newAccountType = accountTypes.getAccountTypeForAccount(newAccount);
13677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1368aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mExistingContactDataReady = false;
1369aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mNewContactDataReady = false;
1370aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mState = new RawContactDeltaList();
1371aebf3206766a05cce290245f09506adb789b6e37Gary Mai        setStateForNewContact(newAccount, newAccountType, oldState, oldAccountType,
1372aebf3206766a05cce290245f09506adb789b6e37Gary Mai                isEditingUserProfile());
1373aebf3206766a05cce290245f09506adb789b6e37Gary Mai        if (mIsEdit) {
1374698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            setStateForExistingContact(isEditingUserProfile(), mRawContacts);
13757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
13767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
13797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // ContactEditor
13807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
13817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void setListener(Listener listener) {
13847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mListener = listener;
13857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void load(String action, Uri lookupUri, Bundle intentExtras) {
13897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAction = action;
13907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mLookupUri = lookupUri;
13917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIntentExtras = intentExtras;
13927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mIntentExtras != null) {
13947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAutoAddToDefaultGroup =
13957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
13967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewLocalProfile =
13977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE);
13987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mDisableDeleteMenuOption =
13997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getBoolean(INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION);
14007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mIntentExtras.containsKey(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR)
14017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    && mIntentExtras.containsKey(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR)) {
14027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mMaterialPalette = new MaterialColorMapUtils.MaterialPalette(
14037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR),
14047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR));
14057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
1406a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai            mRawContactIdToDisplayAlone = mIntentExtras
1407a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai                    .getLong(INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE);
14087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
14107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
14127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void setIntentExtras(Bundle extras) {
14135336e6ef1924162b94942cbd8f69202d553822daGary Mai        getContent().setIntentExtras(extras);
14147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
14157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
14177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onJoinCompleted(Uri uri) {
14187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri, /* joinContactId */ null);
14197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
14207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1421e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
1422e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey    private String getNameToDisplay(Uri contactUri) {
1423c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        // The contact has been deleted or the uri is otherwise no longer right.
1424c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        if (contactUri == null) {
1425c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai            return null;
1426c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        }
1427e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        final ContentResolver resolver = mContext.getContentResolver();
1428e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        final Cursor cursor = resolver.query(contactUri, new String[]{
1429e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                ContactsContract.Contacts.DISPLAY_NAME,
1430e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE}, null, null, null);
1431a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai
1432a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai        if (cursor != null) {
1433a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            try {
1434a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                if (cursor.moveToFirst()) {
1435a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    final String displayName = cursor.getString(0);
1436a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    final String displayNameAlt = cursor.getString(1);
1437a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    cursor.close();
1438a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    return ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
1439a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                            new ContactsPreferences(mContext));
1440a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                }
1441a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            } finally {
1442e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                cursor.close();
1443e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey            }
1444e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        }
1445e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        return null;
1446e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey    }
1447e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
1448e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
14497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
14507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
14517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Uri contactLookupUri, Long joinContactId) {
14527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (hadChanges) {
14537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (saveSucceeded) {
14547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                switch (saveMode) {
14557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    case SaveMode.JOIN:
14567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        break;
14577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    case SaveMode.SPLIT:
14587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        Toast.makeText(mContext, R.string.contactUnlinkedToast, Toast.LENGTH_SHORT)
14597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                                .show();
14607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        break;
14617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    default:
1462e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                        final String displayName = getNameToDisplay(contactLookupUri);
1463b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        final String toastMessage;
1464b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        if (!TextUtils.isEmpty(displayName)) {
1465b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                            toastMessage = getResources().getString(
1466b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                                    R.string.contactSavedNamedToast, displayName);
1467b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        } else {
1468b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                            toastMessage = getResources().getString(R.string.contactSavedToast);
1469b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        }
1470b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        Toast.makeText(mContext, toastMessage, Toast.LENGTH_SHORT).show();
14717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            } else {
14747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
14757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
14767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        switch (saveMode) {
14787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.CLOSE: {
1479581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                Intent resultIntent = null;
14807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null) {
14817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final Uri lookupUri = ContactEditorUtils.maybeConvertToLegacyLookupUri(
14827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            mContext, contactLookupUri, mLookupUri);
1483df86ede2101d902eb95838adf4176c89d9263c89Walter Jang                    if (Flags.getInstance().getBoolean(Experiments.CONTACT_SHEET)) {
1484581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                        resultIntent = ObjectFactory.getContactSheetIntent(mContext, lookupUri);
1485581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                    }
1486581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                    if (resultIntent == null) {
1487581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                        resultIntent = ImplicitIntentsUtil.composeQuickContactIntent(
1488581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                                mContext, lookupUri, ScreenType.EDITOR);
1489581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                        resultIntent.putExtra(QuickContactActivity.EXTRA_CONTACT_EDITED, true);
1490581585d9ad2e7d3d4b65798acaa0fa462d30710dWalter Jang                    }
14917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                } else {
14927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    resultIntent = null;
14937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // It is already saved, so prevent it from being saved again
14957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) mListener.onSaveFinished(resultIntent);
14977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
1499363af60ea23e5a3b945005712a16564ab69db18bGary Mai            case SaveMode.EDITOR: {
15007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // It is already saved, so prevent it from being saved again
15017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
15027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) mListener.onSaveFinished(/* resultIntent= */ null);
15037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
15047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
15057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.JOIN:
15067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null && joinContactId != null) {
15077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    joinAggregate(joinContactId);
15087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
15097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
15107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.RELOAD:
15117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null) {
15127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // If this was in INSERT, we are changing into an EDIT now.
15137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // If it already was an EDIT, we are changing to the new Uri now
15147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mState = new RawContactDeltaList();
15157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    load(Intent.ACTION_EDIT, contactLookupUri, null);
15167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mStatus = Status.LOADING;
15177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    getLoaderManager().restartLoader(LOADER_CONTACT, null, mContactLoaderListener);
15187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
15197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
15207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.SPLIT:
15227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
15237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) {
15247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mListener.onContactSplit(contactLookupUri);
15257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                } else {
15267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.d(TAG, "No listener registered, can not call onSplitFinished");
15277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
15287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
15297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Shows a list of aggregates that can be joined into the currently viewed aggregate.
15347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
15357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param contactLookupUri the fresh URI for the currently edited contact (after saving it)
15367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void showJoinAggregateActivity(Uri contactLookupUri) {
15387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (contactLookupUri == null || !isAdded()) {
15397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mContactIdForJoin = ContentUris.parseId(contactLookupUri);
15437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Intent intent = new Intent(mContext, ContactSelectionActivity.class);
15447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        intent.setAction(UiIntentActions.PICK_JOIN_CONTACT_ACTION);
15457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, mContactIdForJoin);
15467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        startActivityForResult(intent, REQUEST_CODE_JOIN);
15477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
15507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
15517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
15527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Triggers an asynchronous search for aggregation suggestions.
15557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected void acquireAggregationSuggestions(Context context,
15577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            long rawContactId, ValuesDelta valuesDelta) {
15587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionsRawContactId = rawContactId;
15597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine == null) {
15617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine = new AggregationSuggestionEngine(context);
15627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.setListener(this);
15637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.start();
15647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionEngine.setContactId(getContactId());
1567220d10cd7095f5ab803ff6155d7adaa576a8c4ffGary Mai        mAggregationSuggestionEngine.setAccountFilter(
1568220d10cd7095f5ab803ff6155d7adaa576a8c4ffGary Mai                getContent().getCurrentRawContactDelta().getAccountWithDataSet());
15697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionEngine.onNameChange(valuesDelta);
15717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns the contact ID for the currently edited contact or 0 if the contact is new.
15757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private long getContactId() {
15777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        for (RawContactDelta rawContact : mState) {
15787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
15797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (contactId != null) {
15807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return contactId;
15817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
15827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return 0;
15847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15863f990ba4e35a99078d831c041290e574a320caa5Walter Jang    @Override
15877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onAggregationSuggestionChange() {
15887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
15897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if ((activity != null && activity.isFinishing())
15907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                || !isVisible() ||  mState.isEmpty() || mStatus != Status.EDITING) {
15917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        UiClosables.closeQuietly(mAggregationSuggestionPopup);
15957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) {
15977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1600da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        final View anchorView = getAggregationAnchorView();
16017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (anchorView == null) {
16027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return; // Raw contact deleted?
16037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup = new ListPopupWindow(mContext, null);
16057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setAnchorView(anchorView);
16067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setWidth(anchorView.getWidth());
16077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
16087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setAdapter(
16097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                new AggregationSuggestionAdapter(
16107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        getActivity(),
16117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        /* listener =*/ this,
16127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mAggregationSuggestionEngine.getSuggestions()));
16137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
16147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            @Override
16157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
16167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view;
16177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                suggestionView.handleItemClickEvent();
16187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                UiClosables.closeQuietly(mAggregationSuggestionPopup);
16197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAggregationSuggestionPopup = null;
16207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
16217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        });
16227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.show();
16237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1626da20b47c2b85390a2c3772379e71203c5aab513cGary Mai     * Returns the editor view that should be used as the anchor for aggregation suggestions.
16277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1628da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    protected View getAggregationAnchorView() {
1629d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        return getContent().getAggregationAnchorView();
1630d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang    }
1631d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang
16327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Joins the suggested contact (specified by the id's of constituent raw
16347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * contacts), save all changes, and stay in the editor.
16357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
16367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void doJoinSuggestedContact(long[] rawContactIds) {
16377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mStatus != Status.EDITING) {
16387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
16397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.setJoinWithRawContacts(rawContactIds);
16427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        save(SaveMode.RELOAD);
16437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
1646678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai    public void onEditAction(Uri contactLookupUri, long rawContactId) {
1647678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        SuggestionEditConfirmationDialogFragment.show(this, contactLookupUri, rawContactId);
16487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1651678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai     * Abandons the currently edited contact and switches to editing the selected raw contact,
1652678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai     * transferring all the data there
16537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1654678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai    public void doEditSuggestedContact(Uri contactUri, long rawContactId) {
16557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mListener != null) {
16567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // make sure we don't save this contact when closing down
16577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = Status.CLOSING;
1658678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai            mListener.onEditOtherRawContactRequested(contactUri, rawContactId,
1659678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai                    getContent().getCurrentRawContactDelta().getContentValues());
16607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Sets group metadata on all bound editors.
16657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
166692f8ccc1f15df787b7434224857c056721281046Walter Jang    protected void setGroupMetaData() {
1667f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang        if (mGroupMetaData != null) {
1668f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang            getContent().setGroupMetaData(mGroupMetaData);
1669f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang        }
16703f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
16713f990ba4e35a99078d831c041290e574a320caa5Walter Jang
16727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Persist the accumulated editor deltas.
16747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
16757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param joinContactId the raw contact ID to join the contact being saved to after the save,
16767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *         may be null.
16777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1678e3373dceb689209533e95a2cfbfbf1d9008ab6f6Walter Jang    protected boolean doSaveAction(int saveMode, Long joinContactId) {
167949ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        final Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
168049ed2033f83005f92c30068ae33c3138d75e1825Walter Jang                SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
168149ed2033f83005f92c30068ae33c3138d75e1825Walter Jang                ((Activity) mContext).getClass(),
1682363af60ea23e5a3b945005712a16564ab69db18bGary Mai                ContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos,
1683e3373dceb689209533e95a2cfbfbf1d9008ab6f6Walter Jang                JOIN_CONTACT_ID_EXTRA_KEY, joinContactId);
1684dd7d456a080f48d93aa3a9f9b04da0f17a8833a7Wenyi Wang        return startSaveService(mContext, intent, saveMode);
168549ed2033f83005f92c30068ae33c3138d75e1825Walter Jang    }
168649ed2033f83005f92c30068ae33c3138d75e1825Walter Jang
16877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean startSaveService(Context context, Intent intent, int saveMode) {
16887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final boolean result = ContactSaveService.startService(
16897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                context, intent, saveMode);
16907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!result) {
16917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onCancelEditConfirmed();
16927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
16947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
16977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
16987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
16997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
17007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
17017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Performs aggregation with the contact selected by the user from suggestions or A-Z list.
17027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
170349ed2033f83005f92c30068ae33c3138d75e1825Walter Jang    protected void joinAggregate(final long contactId) {
170449ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        final Intent intent = ContactSaveService.createJoinContactsIntent(
1705363af60ea23e5a3b945005712a16564ab69db18bGary Mai                mContext, mContactIdForJoin, contactId, ContactEditorActivity.class,
1706363af60ea23e5a3b945005712a16564ab69db18bGary Mai                ContactEditorActivity.ACTION_JOIN_COMPLETED);
170749ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        mContext.startService(intent);
17083f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
1709b6ca272f26b47ecef8fafe94326c4d553576c521Walter Jang
171031a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void removePhoto() {
171131a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getContent().removePhoto();
171231a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mUpdatedPhotos.remove(String.valueOf(mPhotoRawContactId));
17130e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
17140e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
171531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void updatePhoto(Uri uri) throws FileNotFoundException {
171631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(getActivity(), uri);
171731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0) {
17189bc9ba878cf7f77a2a6b3200a6ab716d13f1affcWenyi Wang            Toast.makeText(mContext, R.string.contactPhotoSavedErrorToast,
171931a74ad969b650eb733e536569254ed3978c4f54Walter Jang                    Toast.LENGTH_SHORT).show();
172031a74ad969b650eb733e536569254ed3978c4f54Walter Jang            return;
17210e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang        }
172231a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mUpdatedPhotos.putParcelable(String.valueOf(mPhotoRawContactId), uri);
172331a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getContent().updatePhoto(uri);
17240e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
17250e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
1726da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    public void setPrimaryPhoto() {
1727da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        getContent().setPrimaryPhoto();
17280e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
17290e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
17300e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    @Override
1731151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang    public void onNameFieldChanged(long rawContactId, ValuesDelta valuesDelta) {
1732151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        final Activity activity = getActivity();
1733151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        if (activity == null || activity.isFinishing()) {
1734151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang            return;
1735151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        }
173645b86d5e83a7d6eca4abe5cdfece2e9050b1809cWalter Jang        acquireAggregationSuggestions(activity, rawContactId, valuesDelta);
1737151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang    }
1738151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang
17395a7a23bdb698b8e741a425c9617c5e33e6314cddWalter Jang    @Override
1740708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang    public void onRebindEditorsForNewContact(RawContactDelta oldState,
1741708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang            AccountWithDataSet oldAccount, AccountWithDataSet newAccount) {
1742708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        mNewContactAccountChanged = true;
1743708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        mAccountWithDataSet = newAccount;
1744708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        rebindEditorsForNewContact(oldState, oldAccount, newAccount);
1745708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang    }
1746708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang
174779658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    @Override
174879658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    public void onBindEditorsFailed() {
174979658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        final Activity activity = getActivity();
175079658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        if (activity != null && !activity.isFinishing()) {
1751363af60ea23e5a3b945005712a16564ab69db18bGary Mai            Toast.makeText(activity, R.string.editor_failed_to_load,
175279658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang                    Toast.LENGTH_SHORT).show();
175379658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang            activity.setResult(Activity.RESULT_CANCELED);
175479658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang            activity.finish();
175579658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        }
175679658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    }
175779658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang
1758d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    @Override
1759d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    public void onEditorsBound() {
17603cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        final Activity activity = getActivity();
17613cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        if (activity == null || activity.isFinishing()) {
17623cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang            return;
17633cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        }
1764d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang        getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupsLoaderListener);
1765d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    }
1766d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang
176731a74ad969b650eb733e536569254ed3978c4f54Walter Jang    @Override
176831a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void onPhotoEditorViewClicked() {
17693f18d6197a54aad10bea9c5cc2c89ca82809e793Walter Jang        // For contacts composed of a single writable raw contact, or raw contacts have no more
17703f18d6197a54aad10bea9c5cc2c89ca82809e793Walter Jang        // than 1 photo, clicking the photo view simply opens the source photo dialog
177131a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getEditorActivity().changePhoto(getPhotoMode());
177231a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
177331a74ad969b650eb733e536569254ed3978c4f54Walter Jang
177431a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private int getPhotoMode() {
1775da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        return getContent().isWritablePhotoSet() ? PhotoActionPopup.Modes.WRITE_ABLE_PHOTO
1776da20b47c2b85390a2c3772379e71203c5aab513cGary Mai                : PhotoActionPopup.Modes.NO_PHOTO;
177731a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
177831a74ad969b650eb733e536569254ed3978c4f54Walter Jang
1779363af60ea23e5a3b945005712a16564ab69db18bGary Mai    private ContactEditorActivity getEditorActivity() {
1780363af60ea23e5a3b945005712a16564ab69db18bGary Mai        return (ContactEditorActivity) getActivity();
178131a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
178231a74ad969b650eb733e536569254ed3978c4f54Walter Jang
1783363af60ea23e5a3b945005712a16564ab69db18bGary Mai    private RawContactEditorView getContent() {
1784363af60ea23e5a3b945005712a16564ab69db18bGary Mai        return (RawContactEditorView) mContent;
17853efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
17863f990ba4e35a99078d831c041290e574a320caa5Walter Jang}
1787