Merge "Don't use hidden QuickContact APIs"
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 5e00118..5b7a735 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -69,7 +69,7 @@
<string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"ይህ ዕውቂያ ከብዙ መለያዎች መረጃ ይዟል።ከንባብ-ብቻ መለያዎች ውስጥ ያሉ ዕውቂያዎች ይደበቃሉ፣አይሰረዙም።"</string>
<string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"ይህን ዕውቂያ መሰረዝ ከብዙ መለያዎች ውስጥ መረጃ ይሰርዛል።"</string>
<string name="deleteConfirmation" msgid="811706994761610640">"ይህ ማንቂያ ይሰረዛል።"</string>
- <string name="menu_discard" msgid="6854657936970228164">"ለውጦችን አስወግድ"</string>
+ <string name="menu_discard" msgid="6854657936970228164">"ለውጦችን ጣለው"</string>
<string name="invalidContactMessage" msgid="8215051456181842274">"ዕውቅያው የለም።"</string>
<string name="createContactShortcutSuccessful" msgid="7874133287558150877">"የእውቂያ መግብር መነሻ ማያ ገጽ ላይ ታክሏል።"</string>
<string name="pickerNewContactHeader" msgid="7750705279843568147">"አዲስ ዕውቂያ ፍጠር"</string>
@@ -203,7 +203,7 @@
<string name="set_default" msgid="4417505153468300351">"ነባሪ አዘጋጅ"</string>
<string name="clear_default" msgid="7193185801596678067">"ነባሪ አጽዳ"</string>
<string name="toast_text_copied" msgid="5143776250008541719">"ፅሁፍ ገልብጧል"</string>
- <string name="cancel_confirmation_dialog_message" msgid="5885724679874403115">" ለውጦችህ ይወገዱ?"</string>
+ <string name="cancel_confirmation_dialog_message" msgid="5885724679874403115">"ለውጦችዎ ይጣሉ?"</string>
<string name="call_type_and_date" msgid="747163730039311423">"<xliff:g id="CALL_TYPE">%1$s</xliff:g> <xliff:g id="CALL_SHORT_DATE">%2$s</xliff:g>"</string>
<string name="profile_display_name" msgid="4127389543625918771">"መገለጫዬን አዘጋጅ"</string>
<string name="enter_contact_name" msgid="1738391320566349924">"የግለሰቡን ስም ተይብ"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 4a9ea8c..9b159cd 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -113,7 +113,7 @@
<string name="callBack" msgid="5498224409038809224">"Передзвонити"</string>
<string name="callAgain" msgid="3197312117049874778">"Набрати знову"</string>
<string name="returnCall" msgid="8171961914203617813">"Зворот. виклик"</string>
- <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"Дод.\" <xliff:g id="EMAIL">%s</xliff:g>\" до контактів?"</string>
+ <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"Додати в контакти <xliff:g id="EMAIL">%s</xliff:g>?"</string>
<string name="description_contact_photo" msgid="3387458082667894062">"фото контакту"</string>
<string name="description_plus_button" msgid="515164827856229880">"плюс"</string>
<string name="exporting_contact_list_progress" msgid="560522409559101193">"<xliff:g id="CURRENT_NUMBER">%s</xliff:g> із <xliff:g id="TOTAL_NUMBER">%s</xliff:g> контактів"</string>
diff --git a/src/com/android/contacts/editor/CancelEditDialogFragment.java b/src/com/android/contacts/editor/CancelEditDialogFragment.java
new file mode 100644
index 0000000..300759e
--- /dev/null
+++ b/src/com/android/contacts/editor/CancelEditDialogFragment.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.editor;
+
+import com.android.contacts.R;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+/**
+ * Asks the user whether to cancel editing the contact.
+ */
+public class CancelEditDialogFragment extends DialogFragment {
+
+ private static final String TAG = "cancelEditor";
+
+ /**
+ * Shows a {@link CancelEditDialogFragment} after setting the given Fragment as the
+ * target of the dialog.
+ */
+ public static void show(ContactEditorBaseFragment fragment) {
+ final CancelEditDialogFragment dialog = new CancelEditDialogFragment();
+ dialog.setTargetFragment(fragment, 0);
+ dialog.show(fragment.getFragmentManager(), TAG);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setMessage(R.string.cancel_confirmation_dialog_message)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int which) {
+ final Listener targetListener = (Listener) getTargetFragment();
+ targetListener.onCancelEditConfirmed();
+ }
+ }
+ )
+ .setNegativeButton(android.R.string.cancel, null)
+ .create();
+ }
+
+ /**
+ * Callbacks for {@link CancelEditDialogFragment} hosts.
+ */
+ public interface Listener {
+
+ /**
+ * Invoked when the user confirms that they want to cancel editing the contact.
+ */
+ void onCancelEditConfirmed();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index 5361155..aee1f73 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -16,12 +16,14 @@
package com.android.contacts.editor;
+import com.google.common.collect.ImmutableList;
+
import com.android.contacts.R;
import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor;
-import com.android.contacts.editor.ContactEditorBaseFragment.Listener;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.model.account.AccountWithDataSet;
-import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -36,28 +38,10 @@
public class CompactContactEditorFragment extends ContactEditorBaseFragment
implements ContactEditor {
- private Context mContext;
- private Listener mListener;
-
- private String mAction;
- private Uri mLookupUri;
- private Bundle mIntentExtras;
-
- private LinearLayout mContent;
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mContext = activity;
- }
-
- @Override
- public void setListener(Listener listener) {
- mListener = listener;
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ setHasOptionsMenu(true);
+
final View view = inflater.inflate(
R.layout.compact_contact_editor_fragment, container, false);
mContent = (LinearLayout) view.findViewById(R.id.editors);
@@ -65,12 +49,39 @@
}
@Override
- public void load(String action, Uri lookupUri, Bundle intentExtras) {
- mAction = action;
- mLookupUri = lookupUri;
- mIntentExtras = intentExtras;
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (mStatus == Status.SUB_ACTIVITY) {
+ mStatus = Status.EDITING;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
}
+ //
+ // ContactEditorBaseFragment
+ //
+
+ @Override
+ protected void bindEditorsForExistingContact(String displayName, boolean isUserProfile,
+ ImmutableList<RawContact> rawContacts) {
+ }
+
+ @Override
+ protected void bindEditorsForNewContact(AccountWithDataSet account,
+ AccountType accountType) {
+ }
+
+ @Override
+ protected void bindEditors() {
+ }
+
+ @Override
+ protected void bindGroupMetaData() {
+ }
+
+ //
+ // ContactEditor
+ //
+
@Override
public void setIntentExtras(Bundle extras) {
}
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 3eadaed..4b7af5b 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -16,28 +16,112 @@
package com.android.contacts.editor;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
+import com.android.contacts.activities.ContactEditorBaseActivity;
+import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.quickcontact.QuickContactActivity;
+import com.android.contacts.util.HelpUtils;
+import com.android.contacts.util.PhoneCapabilityTester;
+import android.accounts.Account;
+import android.app.Activity;
import android.app.Fragment;
+import android.app.LoaderManager;
+import android.content.ActivityNotFoundException;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.CursorLoader;
import android.content.Intent;
+import android.content.Loader;
+import android.database.Cursor;
import android.graphics.Rect;
+import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
+import android.os.SystemClock;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.QuickContact;
+import android.provider.ContactsContract.RawContacts;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.LinearLayout;
+import android.widget.Toast;
import java.util.ArrayList;
+import java.util.List;
/**
* Base Fragment for contact editors.
*/
-abstract public class ContactEditorBaseFragment extends Fragment {
+abstract public class ContactEditorBaseFragment extends Fragment implements
+ ContactEditor, SplitContactConfirmationDialogFragment.Listener {
- protected static final String TAG = "ContactCompactEditor";
+ protected static final String TAG = "ContactEditor";
+
+ protected static final int LOADER_DATA = 1;
+ protected static final int LOADER_GROUPS = 2;
+
+ private static final String KEY_ACTION = "action";
+ private static final String KEY_URI = "uri";
+ private static final String KEY_AUTO_ADD_TO_DEFAULT_GROUP = "autoAddToDefaultGroup";
+ private static final String KEY_DISABLE_DELETE_MENU_OPTION = "disableDeleteMenuOption";
+ private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
+
+ private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
+
+ private static final String KEY_RAW_CONTACTS = "rawContacts";
+
+ private static final String KEY_EDIT_STATE = "state";
+ private static final String KEY_STATUS = "status";
+
+ private static final String KEY_HAS_NEW_CONTACT = "hasNewContact";
+ private static final String KEY_NEW_CONTACT_READY = "newContactDataReady";
+
+ private static final String KEY_IS_EDIT = "isEdit";
+ private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
+
+ // Phone option menus
+ private static final String KEY_SEND_TO_VOICE_MAIL_STATE = "sendToVoicemailState";
+ private static final String KEY_ARE_PHONE_OPTIONS_CHANGEABLE = "arePhoneOptionsChangable";
+ private static final String KEY_CUSTOM_RINGTONE = "customRingtone";
+
+ private static final String KEY_IS_USER_PROFILE = "isUserProfile";
+
+ private static final String KEY_ENABLED = "enabled";
+
+ protected static final int REQUEST_CODE_JOIN = 0;
+ protected static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
+ protected static final int REQUEST_CODE_PICK_RINGTONE = 2;
+
+ /**
+ * An intent extra that forces the editor to add the edited contact
+ * to the default group (e.g. "My Contacts").
+ */
+ public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
+
+ public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
+
+ public static final String INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION =
+ "disableDeleteMenuOption";
/**
* Callbacks for Activities that host contact editors Fragments.
@@ -98,6 +182,662 @@
void onDeleteRequested(Uri contactUri);
}
+ protected Context mContext;
+ protected Listener mListener;
+
+ protected LinearLayout mContent;
+
+ //
+ // Parameters passed in on {@link #load}
+ //
+ protected String mAction;
+ protected Uri mLookupUri;
+ protected Bundle mIntentExtras;
+ protected boolean mAutoAddToDefaultGroup;
+ protected boolean mDisableDeleteMenuOption;
+ protected boolean mNewLocalProfile;
+
+ //
+ // Helpers
+ //
+ protected ContactEditorUtils mEditorUtils;
+ protected RawContactDeltaComparator mComparator;
+ protected ViewIdGenerator mViewIdGenerator;
+
+ //
+ // Loaded data
+ //
+ // Used to temporarily store existing contact data during a rebind call (i.e. account switch)
+ protected ImmutableList<RawContact> mRawContacts;
+ protected Cursor mGroupMetaData;
+
+ //
+ // Contact editor state
+ //
+ protected RawContactDeltaList mState;
+ protected int mStatus;
+
+ // Whether to show the new contact blank form and if it's corresponding delta is ready.
+ protected boolean mHasNewContact;
+ protected boolean mNewContactDataReady;
+
+ // Whether it's an edit of existing contact and if it's corresponding delta is ready.
+ protected boolean mIsEdit;
+ protected boolean mExistingContactDataReady;
+
+ // Phone specific option menus
+ private boolean mSendToVoicemailState;
+ private boolean mArePhoneOptionsChangable;
+ private String mCustomRingtone;
+
+ protected boolean mIsUserProfile;
+
+ // Whether editors and options menu items are enabled
+ protected boolean mEnabled = true;
+
+ /**
+ * The contact data loader listener.
+ */
+ protected final LoaderManager.LoaderCallbacks<Contact> mDataLoaderListener =
+ new LoaderManager.LoaderCallbacks<Contact>() {
+
+ protected long mLoaderStartTime;
+
+ @Override
+ public Loader<Contact> onCreateLoader(int id, Bundle args) {
+ mLoaderStartTime = SystemClock.elapsedRealtime();
+ return new ContactLoader(mContext, mLookupUri, true);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Contact> loader, Contact data) {
+ final long loaderCurrentTime = SystemClock.elapsedRealtime();
+ Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
+ if (!data.isLoaded()) {
+ // Item has been deleted. Close activity without saving again.
+ Log.i(TAG, "No contact found. Closing activity");
+ mStatus = Status.CLOSING;
+ if (mListener != null) mListener.onContactNotFound();
+ return;
+ }
+
+ mStatus = Status.EDITING;
+ mLookupUri = data.getLookupUri();
+ final long setDataStartTime = SystemClock.elapsedRealtime();
+ setData(data);
+ final long setDataEndTime = SystemClock.elapsedRealtime();
+
+ Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime - setDataStartTime));
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Contact> loader) {
+ }
+ };
+
+ /**
+ * The group meta data loader listener.
+ */
+ protected final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener =
+ new LoaderManager.LoaderCallbacks<Cursor>() {
+
+ @Override
+ public CursorLoader onCreateLoader(int id, Bundle args) {
+ return new GroupMetaDataLoader(mContext, ContactsContract.Groups.CONTENT_URI);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ mGroupMetaData = data;
+ bindGroupMetaData();
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ }
+ };
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mContext = activity;
+ mEditorUtils = ContactEditorUtils.getInstance(mContext);
+ mComparator = new RawContactDeltaComparator(mContext);
+ }
+
+ @Override
+ public void onCreate(Bundle savedState) {
+ if (savedState != null) {
+ // Restore mUri before calling super.onCreate so that onInitializeLoaders
+ // would already have a uri and an action to work with
+ mAction = savedState.getString(KEY_ACTION);
+ mLookupUri = savedState.getParcelable(KEY_URI);
+ }
+
+ super.onCreate(savedState);
+
+ if (savedState == null) {
+ mViewIdGenerator = new ViewIdGenerator();
+ } else {
+ mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
+
+ mAutoAddToDefaultGroup = savedState.getBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP);
+ mDisableDeleteMenuOption = savedState.getBoolean(KEY_DISABLE_DELETE_MENU_OPTION);
+ mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
+
+ mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
+ KEY_RAW_CONTACTS));
+ // NOTE: mGroupMetaData is not saved/restored
+
+ // Read state from savedState. No loading involved here
+ mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE);
+ mStatus = savedState.getInt(KEY_STATUS);
+
+ mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT);
+ mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY);
+
+ mIsEdit = savedState.getBoolean(KEY_IS_EDIT);
+ mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY);
+
+ // Phone specific options menus
+ mSendToVoicemailState = savedState.getBoolean(KEY_SEND_TO_VOICE_MAIL_STATE);
+ mArePhoneOptionsChangable = savedState.getBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE);
+ mCustomRingtone = savedState.getString(KEY_CUSTOM_RINGTONE);
+
+ mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
+
+ mEnabled = savedState.getBoolean(KEY_ENABLED);
+ }
+
+ // mState can still be null because it may not have have finished loading before
+ // onSaveInstanceState was called.
+ if (mState == null) {
+ mState = new RawContactDeltaList();
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ validateAction(mAction);
+
+ if (mState.isEmpty()) {
+ // The delta list may not have finished loading before orientation change happens.
+ // In this case, there will be a saved state but deltas will be missing. Reload from
+ // database.
+ if (Intent.ACTION_EDIT.equals(mAction)) {
+ // Either...
+ // 1) orientation change but load never finished.
+ // or
+ // 2) not an orientation change. data needs to be loaded for first time.
+ getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener);
+ }
+ } else {
+ // Orientation change, we already have mState, it was loaded by onCreate
+ bindEditors();
+ }
+
+ // Handle initial actions only when existing state missing
+ if (savedInstanceState == null) {
+ if (Intent.ACTION_EDIT.equals(mAction)) {
+ mIsEdit = true;
+ } else if (Intent.ACTION_INSERT.equals(mAction)) {
+ mHasNewContact = true;
+ final Account account = mIntentExtras == null ? null :
+ (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
+ final String dataSet = mIntentExtras == null ? null :
+ mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
+
+ if (account != null) {
+ // Account specified in Intent
+ createContact(new AccountWithDataSet(account.name, account.type, dataSet));
+ } else {
+ // No Account specified. Let the user choose
+ // Load Accounts async so that we can present them
+ selectAccountAndCreateContact();
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the requested action is valid.
+ *
+ * @param action The action to test.
+ * @throws IllegalArgumentException when the action is invalid.
+ */
+ private static void validateAction(String action) {
+ if (Intent.ACTION_EDIT.equals(action) || Intent.ACTION_INSERT.equals(action) ||
+ ContactEditorBaseActivity.ACTION_SAVE_COMPLETED.equals(action)) {
+ return;
+ }
+ throw new IllegalArgumentException("Unknown Action String " + action +
+ ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT + " or " +
+ ContactEditorBaseActivity.ACTION_SAVE_COMPLETED);
+ }
+
+ @Override
+ public void onStart() {
+ getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener);
+ super.onStart();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putString(KEY_ACTION, mAction);
+ outState.putParcelable(KEY_URI, mLookupUri);
+ outState.putBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP, mAutoAddToDefaultGroup);
+ outState.putBoolean(KEY_DISABLE_DELETE_MENU_OPTION, mDisableDeleteMenuOption);
+ outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile);
+
+ outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
+
+ outState.putParcelableArrayList(KEY_RAW_CONTACTS, mRawContacts == null ?
+ Lists.<RawContact>newArrayList() : Lists.newArrayList(mRawContacts));
+ // NOTE: mGroupMetaData is not saved
+
+ if (hasValidState()) {
+ // Store entities with modifications
+ outState.putParcelable(KEY_EDIT_STATE, mState);
+ }
+ outState.putInt(KEY_STATUS, mStatus);
+ outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact);
+ outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady);
+ outState.putBoolean(KEY_IS_EDIT, mIsEdit);
+ outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady);
+
+ // Phone specific options
+ outState.putBoolean(KEY_SEND_TO_VOICE_MAIL_STATE, mSendToVoicemailState);
+ outState.putBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE, mArePhoneOptionsChangable);
+ outState.putString(KEY_CUSTOM_RINGTONE, mCustomRingtone);
+
+ outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
+ outState.putBoolean(KEY_ENABLED, mEnabled);
+
+ super.onSaveInstanceState(outState);
+ }
+
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case REQUEST_CODE_ACCOUNTS_CHANGED: {
+ // Bail if the account selector was not successful.
+ if (resultCode != Activity.RESULT_OK) {
+ mListener.onReverted();
+ return;
+ }
+ // If there's an account specified, use it.
+ if (data != null) {
+ AccountWithDataSet account = data.getParcelableExtra(
+ Intents.Insert.EXTRA_ACCOUNT);
+ if (account != null) {
+ createContact(account);
+ return;
+ }
+ }
+ // If there isn't an account specified, then this is likely a phone-local
+ // contact, so we should continue setting up the editor by automatically selecting
+ // the most appropriate account.
+ createContact();
+ break;
+ }
+ case REQUEST_CODE_PICK_RINGTONE: {
+ if (data != null) {
+ final Uri pickedUri = data.getParcelableExtra(
+ RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+ handleRingtonePicked(pickedUri);
+ }
+ break;
+ }
+ }
+ }
+
+ private void handleRingtonePicked(Uri pickedUri) {
+ if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) {
+ mCustomRingtone = null;
+ } else {
+ mCustomRingtone = pickedUri.toString();
+ }
+ Intent intent = ContactSaveService.createSetRingtone(
+ mContext, mLookupUri, mCustomRingtone);
+ mContext.startService(intent);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
+ inflater.inflate(R.menu.edit_contact, menu);
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
+ // because the custom action bar contains the "save" button now (not the overflow menu).
+ // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
+ final MenuItem doneMenu = menu.findItem(R.id.menu_done);
+ final MenuItem splitMenu = menu.findItem(R.id.menu_split);
+ final MenuItem joinMenu = menu.findItem(R.id.menu_join);
+ final MenuItem helpMenu = menu.findItem(R.id.menu_help);
+ final MenuItem discardMenu = menu.findItem(R.id.menu_discard);
+ final MenuItem sendToVoiceMailMenu = menu.findItem(R.id.menu_send_to_voicemail);
+ final MenuItem ringToneMenu = menu.findItem(R.id.menu_set_ringtone);
+ final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
+ deleteMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ deleteMenu.setIcon(R.drawable.ic_delete_white_24dp);
+
+ // Set visibility of menus
+ doneMenu.setVisible(false);
+
+ // Discard menu is only available if at least one raw contact is editable
+ discardMenu.setVisible(mState != null &&
+ mState.getFirstWritableRawContact(mContext) != null);
+
+ // help menu depending on whether this is inserting or editing
+ if (Intent.ACTION_INSERT.equals(mAction)) {
+ HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_add);
+ splitMenu.setVisible(false);
+ joinMenu.setVisible(false);
+ deleteMenu.setVisible(false);
+ } else if (Intent.ACTION_EDIT.equals(mAction)) {
+ HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_edit);
+ // Split only if more than one raw profile and not a user profile
+ splitMenu.setVisible(mState.size() > 1 && !isEditingUserProfile());
+ // Cannot join a user profile
+ joinMenu.setVisible(!isEditingUserProfile());
+ deleteMenu.setVisible(!mDisableDeleteMenuOption);
+ } else {
+ // something else, so don't show the help menu
+ helpMenu.setVisible(false);
+ }
+
+ // Hide telephony-related settings (ringtone, send to voicemail)
+ // if we don't have a telephone or are editing a new contact.
+ sendToVoiceMailMenu.setChecked(mSendToVoicemailState);
+ sendToVoiceMailMenu.setVisible(mArePhoneOptionsChangable);
+ ringToneMenu.setVisible(mArePhoneOptionsChangable);
+
+ int size = menu.size();
+ for (int i = 0; i < size; i++) {
+ menu.getItem(i).setEnabled(mEnabled);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ case R.id.menu_done:
+ return save(SaveMode.CLOSE);
+ case R.id.menu_discard:
+ return revert();
+ case R.id.menu_delete:
+ if (mListener != null) mListener.onDeleteRequested(mLookupUri);
+ return true;
+ case R.id.menu_split:
+ return doSplitContactAction();
+ case R.id.menu_join:
+ return doJoinContactAction();
+ case R.id.menu_set_ringtone:
+ doPickRingtone();
+ return true;
+ case R.id.menu_send_to_voicemail:
+ // Update state and save
+ mSendToVoicemailState = !mSendToVoicemailState;
+ item.setChecked(mSendToVoicemailState);
+ final Intent intent = ContactSaveService.createSetSendToVoicemail(
+ mContext, mLookupUri, mSendToVoicemailState);
+ mContext.startService(intent);
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean revert() {
+ if (mState.isEmpty() || !hasPendingChanges()) {
+ onSplitContactConfirmed();
+ } else {
+ CancelEditDialogFragment.show(this);
+ }
+ return true;
+ }
+
+ @Override
+ public void onSplitContactConfirmed() {
+ // When this Fragment is closed we don't want it to auto-save
+ mStatus = Status.CLOSING;
+ if (mListener != null) mListener.onReverted();
+ }
+
+ private boolean doSplitContactAction() {
+ if (!hasValidState()) return false;
+
+ SplitContactConfirmationDialogFragment.show(this);
+ return true;
+ }
+
+ private boolean doJoinContactAction() {
+ if (!hasValidState()) {
+ return false;
+ }
+
+ // If we just started creating a new contact and haven't added any data, it's too
+ // early to do a join
+ if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) {
+ Toast.makeText(mContext, R.string.toast_join_with_empty_contact,
+ Toast.LENGTH_LONG).show();
+ return true;
+ }
+
+ return save(SaveMode.JOIN);
+ }
+
+ private void doPickRingtone() {
+ final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+ // Allow user to pick 'Default'
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
+ // Show only ringtones
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
+ // Allow the user to pick a silent ringtone
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
+
+ final Uri ringtoneUri;
+ if (mCustomRingtone != null) {
+ ringtoneUri = Uri.parse(mCustomRingtone);
+ } else {
+ // Otherwise pick default ringtone Uri so that something is selected.
+ ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+ }
+
+ // Put checkmark next to the current ringtone for this contact
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
+
+ // Launch!
+ try {
+ startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE);
+ } catch (ActivityNotFoundException ex) {
+ Toast.makeText(mContext, R.string.missing_app, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /**
+ * Check if our internal {@link #mState} is valid, usually checked before
+ * performing user actions.
+ */
+ protected boolean hasValidState() {
+ return mState.size() > 0;
+ }
+
+ protected boolean isEditingUserProfile() {
+ return mNewLocalProfile || mIsUserProfile;
+ }
+
+ /**
+ * Return true if there are any edits to the current contact which need to
+ * be saved.
+ */
+ protected boolean hasPendingChanges() {
+ final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
+ return RawContactModifier.hasChanges(mState, accountTypes);
+ }
+
+ //
+ // Account creation
+ //
+
+ private void selectAccountAndCreateContact() {
+ // If this is a local profile, then skip the logic about showing the accounts changed
+ // activity and create a phone-local contact.
+ if (mNewLocalProfile) {
+ createContact(null);
+ return;
+ }
+
+ // If there is no default account or the accounts have changed such that we need to
+ // prompt the user again, then launch the account prompt.
+ if (mEditorUtils.shouldShowAccountChangedNotification()) {
+ Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
+ mStatus = Status.SUB_ACTIVITY;
+ startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED);
+ } else {
+ // Otherwise, there should be a default account. Then either create a local contact
+ // (if default account is null) or create a contact with the specified account.
+ AccountWithDataSet defaultAccount = mEditorUtils.getDefaultAccount();
+ createContact(defaultAccount);
+ }
+ }
+
+ /**
+ * Create a contact by automatically selecting the first account. If there's no available
+ * account, a device-local contact should be created.
+ */
+ protected void createContact() {
+ final List<AccountWithDataSet> accounts =
+ AccountTypeManager.getInstance(mContext).getAccounts(true);
+ // No Accounts available. Create a phone-local contact.
+ if (accounts.isEmpty()) {
+ createContact(null);
+ return;
+ }
+
+ // We have an account switcher in "create-account" screen, so don't need to ask a user to
+ // select an account here.
+ createContact(accounts.get(0));
+ }
+
+ /**
+ * Shows account creation screen associated with a given account.
+ *
+ * @param account may be null to signal a device-local contact should be created.
+ */
+ protected void createContact(AccountWithDataSet account) {
+ final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
+ final AccountType accountType = accountTypes.getAccountTypeForAccount(account);
+
+ if (accountType.getCreateContactActivityClassName() != null) {
+ if (mListener != null) {
+ mListener.onCustomCreateContactActivityRequested(account, mIntentExtras);
+ }
+ } else {
+ bindEditorsForNewContact(account, accountType);
+ }
+ }
+
+ //
+ // Data binding
+ //
+
+ private void setData(Contact contact) {
+
+ // If we have already loaded data, we do not want to change it here to not confuse the user
+ if (!mState.isEmpty()) {
+ Log.v(TAG, "Ignoring background change. This will have to be rebased later");
+ return;
+ }
+
+ // See if this edit operation needs to be redirected to a custom editor
+ mRawContacts = contact.getRawContacts();
+ if (mRawContacts.size() == 1) {
+ RawContact rawContact = mRawContacts.get(0);
+ String type = rawContact.getAccountTypeString();
+ String dataSet = rawContact.getDataSet();
+ AccountType accountType = rawContact.getAccountType(mContext);
+ if (accountType.getEditContactActivityClassName() != null &&
+ !accountType.areContactsWritable()) {
+ if (mListener != null) {
+ String name = rawContact.getAccountName();
+ long rawContactId = rawContact.getId();
+ mListener.onCustomEditContactActivityRequested(
+ new AccountWithDataSet(name, type, dataSet),
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+ mIntentExtras, true);
+ }
+ return;
+ }
+ }
+
+ String displayName = null;
+ // Check for writable raw contacts. If there are none, then we need to create one so user
+ // can edit. For the user profile case, there is already an editable contact.
+ if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
+ mHasNewContact = true;
+
+ // This is potentially an asynchronous call and will add deltas to list.
+ selectAccountAndCreateContact();
+ displayName = contact.getDisplayName();
+ }
+
+ // This also adds deltas to list
+ // If displayName is null at this point it is simply ignored later on by the editor.
+ bindEditorsForExistingContact(displayName, contact.isUserProfile(),
+ mRawContacts);
+
+ bindMenuItemsForPhone(contact);
+ }
+
+ private void bindMenuItemsForPhone(Contact contact) {
+ if (contact != null) {
+ mSendToVoicemailState = contact.isSendToVoicemail();
+ mCustomRingtone = contact.getCustomRingtone();
+ mArePhoneOptionsChangable = !contact.isDirectoryEntry()
+ && PhoneCapabilityTester.isPhone(mContext);
+ }
+ }
+
+ // TODO: add javadocs after these are finalized
+ abstract protected void bindEditorsForExistingContact(String displayName, boolean isUserProfile,
+ ImmutableList<RawContact> rawContacts);
+ abstract protected void bindEditorsForNewContact(AccountWithDataSet account,
+ final AccountType accountType);
+ abstract protected void bindEditors();
+ abstract protected void bindGroupMetaData();
+
+ //
+ // ContactEditor
+ //
+
+ @Override
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void load(String action, Uri lookupUri, Bundle intentExtras) {
+ mAction = action;
+ mLookupUri = lookupUri;
+ mIntentExtras = intentExtras;
+
+ if (mIntentExtras != null) {
+ mAutoAddToDefaultGroup =
+ mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
+ mNewLocalProfile =
+ mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE);
+ mDisableDeleteMenuOption =
+ mIntentExtras.getBoolean(INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION);
+ }
+ }
+
/**
* Returns a legacy version of the given contactLookupUri if a legacy Uri was originally
* passed to the contact editor.
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 0a8a967..7fb4378 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -16,41 +16,29 @@
package com.android.contacts.editor;
-import android.accounts.Account;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
-import android.app.LoaderManager;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.ActivityNotFoundException;
import android.content.ContentUris;
import android.content.Context;
-import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.Loader;
-import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
-import android.os.SystemClock;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -61,16 +49,10 @@
import android.widget.Toast;
import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
-import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
import com.android.contacts.activities.ContactEditorActivity;
import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor;
-import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor.SaveMode;
-import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor.Status;
import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.model.ContactLoader;
import com.android.contacts.common.model.RawContact;
import com.android.contacts.common.model.RawContactDelta;
import com.android.contacts.common.model.RawContactDeltaList;
@@ -85,8 +67,6 @@
import com.android.contacts.editor.Editor.EditorListener;
import com.android.contacts.list.UiIntentActions;
import com.android.contacts.util.ContactPhotoUtils;
-import com.android.contacts.util.HelpUtils;
-import com.android.contacts.util.PhoneCapabilityTester;
import com.android.contacts.util.UiClosables;
import com.google.common.collect.ImmutableList;
@@ -105,100 +85,31 @@
AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
RawContactReadOnlyEditorView.Listener {
- private static final int LOADER_DATA = 1;
- private static final int LOADER_GROUPS = 2;
-
- private static final String KEY_URI = "uri";
- private static final String KEY_ACTION = "action";
- private static final String KEY_EDIT_STATE = "state";
- private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester";
- private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
- private static final String KEY_CURRENT_PHOTO_URI = "currentphotouri";
+ // Joins
private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin";
private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin";
- private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions";
- private static final String KEY_ENABLED = "enabled";
- private static final String KEY_STATUS = "status";
- private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
- private static final String KEY_IS_USER_PROFILE = "isUserProfile";
- private static final String KEY_DISABLE_DELETE_MENU_OPTION = "disableDeleteMenuOption";
- private static final String KEY_UPDATED_PHOTOS = "updatedPhotos";
- private static final String KEY_IS_EDIT = "isEdit";
- private static final String KEY_HAS_NEW_CONTACT = "hasNewContact";
- private static final String KEY_NEW_CONTACT_READY = "newContactDataReady";
- private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
- private static final String KEY_RAW_CONTACTS = "rawContacts";
- private static final String KEY_SEND_TO_VOICE_MAIL_STATE = "sendToVoicemailState";
- private static final String KEY_CUSTOM_RINGTONE = "customRingtone";
- private static final String KEY_ARE_PHONE_OPTIONS_CHANGEABLE = "arePhoneOptionsChangable";
+
private static final String KEY_EXPANDED_EDITORS = "expandedEditors";
+ // Photos
+ private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester";
+ private static final String KEY_CURRENT_PHOTO_URI = "currentphotouri";
+ private static final String KEY_UPDATED_PHOTOS = "updatedPhotos";
+
+ // Aggregations
+ private static final String KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID =
+ "aggregationSuggestionsRawContactId";
+
public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
- /**
- * An intent extra that forces the editor to add the edited contact
- * to the default group (e.g. "My Contacts").
- */
- public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
-
- public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
-
- public static final String INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION =
- "disableDeleteMenuOption";
-
- private static final int REQUEST_CODE_JOIN = 0;
- private static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
- private static final int REQUEST_CODE_PICK_RINGTONE = 2;
-
- private Context mContext;
- private Listener mListener;
-
- private LinearLayout mContent;
-
- //
- // Parameters passed in on {@link #load}
- //
- private String mAction;
- private Uri mLookupUri;
- private Bundle mIntentExtras;
- private boolean mAutoAddToDefaultGroup;
- private boolean mDisableDeleteMenuOption = false;
- private boolean mNewLocalProfile = false;
-
//
// Helpers
//
- private ContactEditorUtils mEditorUtils;
- private RawContactDeltaComparator mComparator;
- private ViewIdGenerator mViewIdGenerator;
private AggregationSuggestionEngine mAggregationSuggestionEngine;
//
- // Loaded data
- //
- // Used to temporarily store existing contact data during a rebind call (i.e. account switch)
- private ImmutableList<RawContact> mRawContacts;
- private Cursor mGroupMetaData;
-
- //
// Contact editor state
//
- private RawContactDeltaList mState;
- private int mStatus;
-
- // Whether to show the new contact blank form and if it's corresponding delta is ready.
- private boolean mHasNewContact = false;
- private boolean mNewContactDataReady = false;
-
- // Whether it's an edit of existing contact and if it's corresponding delta is ready.
- private boolean mIsEdit = false;
- private boolean mExistingContactDataReady = false;
-
- // Variables related to phone specific option menus
- private boolean mSendToVoicemailState;
- private boolean mArePhoneOptionsChangable;
- private String mCustomRingtone;
-
// Joins
private long mContactIdForJoin;
private boolean mContactWritableForJoin;
@@ -206,11 +117,6 @@
// Used to store which raw contact editors have been expanded. Keyed on raw contact ids.
private HashMap<Long, Boolean> mExpandedEditors = new HashMap<Long, Boolean>();
- private boolean mIsUserProfile = false;
-
- // Whether editors and options menu items are enabled
- private boolean mEnabled = true;
-
// Whether the name editor should receive focus after being bound
private boolean mRequestFocus;
@@ -315,14 +221,6 @@
}
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mContext = activity;
- mEditorUtils = ContactEditorUtils.getInstance(mContext);
- mComparator = new RawContactDeltaComparator(mContext);
- }
-
- @Override
public void onStop() {
super.onStop();
@@ -354,186 +252,35 @@
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- validateAction(mAction);
-
- if (mState.isEmpty()) {
- // The delta list may not have finished loading before orientation change happens.
- // In this case, there will be a saved state but deltas will be missing. Reload from
- // database.
- if (Intent.ACTION_EDIT.equals(mAction)) {
- // Either...
- // 1) orientation change but load never finished.
- // or
- // 2) not an orientation change. data needs to be loaded for first time.
- getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener);
- }
- } else {
- // Orientation change, we already have mState, it was loaded by onCreate
- bindEditors();
- }
-
- // Handle initial actions only when existing state missing
- if (savedInstanceState == null) {
- if (Intent.ACTION_EDIT.equals(mAction)) {
- mIsEdit = true;
- } else if (Intent.ACTION_INSERT.equals(mAction)) {
- mHasNewContact = true;
- final Account account = mIntentExtras == null ? null :
- (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
- final String dataSet = mIntentExtras == null ? null :
- mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
-
- if (account != null) {
- // Account specified in Intent
- createContact(new AccountWithDataSet(account.name, account.type, dataSet));
- } else {
- // No Account specified. Let the user choose
- // Load Accounts async so that we can present them
- selectAccountAndCreateContact();
- }
- }
- }
- }
-
- /**
- * Checks if the requested action is valid.
- *
- * @param action The action to test.
- * @throws IllegalArgumentException when the action is invalid.
- */
- private void validateAction(String action) {
- if (Intent.ACTION_EDIT.equals(action) || Intent.ACTION_INSERT.equals(action) ||
- ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(action)) {
- return;
- }
- throw new IllegalArgumentException("Unknown Action String " + mAction +
- ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT + " or " +
- ContactEditorActivity.ACTION_SAVE_COMPLETED);
- }
-
- @Override
public void onStart() {
getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener);
super.onStart();
}
@Override
- public void load(String action, Uri lookupUri, Bundle intentExtras) {
- mAction = action;
- mLookupUri = lookupUri;
- mIntentExtras = intentExtras;
- mAutoAddToDefaultGroup = mIntentExtras != null
- && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
- mNewLocalProfile = mIntentExtras != null
- && mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE);
- mDisableDeleteMenuOption = mIntentExtras != null
- && mIntentExtras.getBoolean(INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION);
- }
-
- @Override
- public void setListener(Listener value) {
- mListener = value;
- }
-
- @Override
public void onCreate(Bundle savedState) {
- if (savedState != null) {
- // Restore mUri before calling super.onCreate so that onInitializeLoaders
- // would already have a uri and an action to work with
- mLookupUri = savedState.getParcelable(KEY_URI);
- mAction = savedState.getString(KEY_ACTION);
- }
-
super.onCreate(savedState);
- if (savedState == null) {
- // If savedState is non-null, onRestoreInstanceState() will restore the generator.
- mViewIdGenerator = new ViewIdGenerator();
- } else {
- // Read state from savedState. No loading involved here
- mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE);
- mRawContactIdRequestingPhoto = savedState.getLong(
- KEY_RAW_CONTACT_ID_REQUESTING_PHOTO);
- mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
- mCurrentPhotoUri = savedState.getParcelable(KEY_CURRENT_PHOTO_URI);
+ if (savedState != null) {
+ // Joins
mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN);
mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN);
- mAggregationSuggestionsRawContactId = savedState.getLong(KEY_SHOW_JOIN_SUGGESTIONS);
- mEnabled = savedState.getBoolean(KEY_ENABLED);
- mStatus = savedState.getInt(KEY_STATUS);
- mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
- mDisableDeleteMenuOption = savedState.getBoolean(KEY_DISABLE_DELETE_MENU_OPTION);
- mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
- mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
- mIsEdit = savedState.getBoolean(KEY_IS_EDIT);
- mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT);
- mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY);
- mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY);
- mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
- KEY_RAW_CONTACTS));
- mSendToVoicemailState = savedState.getBoolean(KEY_SEND_TO_VOICE_MAIL_STATE);
- mCustomRingtone = savedState.getString(KEY_CUSTOM_RINGTONE);
- mArePhoneOptionsChangable = savedState.getBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE);
+
mExpandedEditors = (HashMap<Long, Boolean>)
savedState.getSerializable(KEY_EXPANDED_EDITORS);
+
+ // NOTE: mRequestFocus and mDefaultDisplayName are not saved/restored
+
+ // Photos
+ mRawContactIdRequestingPhoto = savedState.getLong(
+ KEY_RAW_CONTACT_ID_REQUESTING_PHOTO);
+ mCurrentPhotoUri = savedState.getParcelable(KEY_CURRENT_PHOTO_URI);
+ mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
+
+ // Aggregations
+ mAggregationSuggestionsRawContactId = savedState.getLong(
+ KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID);
}
-
- // mState can still be null because it may not have have finished loading before
- // onSaveInstanceState was called.
- if (mState == null) {
- mState = new RawContactDeltaList();
- }
- }
-
- public void setData(Contact contact) {
-
- // If we have already loaded data, we do not want to change it here to not confuse the user
- if (!mState.isEmpty()) {
- Log.v(TAG, "Ignoring background change. This will have to be rebased later");
- return;
- }
-
- // See if this edit operation needs to be redirected to a custom editor
- mRawContacts = contact.getRawContacts();
- if (mRawContacts.size() == 1) {
- RawContact rawContact = mRawContacts.get(0);
- String type = rawContact.getAccountTypeString();
- String dataSet = rawContact.getDataSet();
- AccountType accountType = rawContact.getAccountType(mContext);
- if (accountType.getEditContactActivityClassName() != null &&
- !accountType.areContactsWritable()) {
- if (mListener != null) {
- String name = rawContact.getAccountName();
- long rawContactId = rawContact.getId();
- mListener.onCustomEditContactActivityRequested(
- new AccountWithDataSet(name, type, dataSet),
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
- mIntentExtras, true);
- }
- return;
- }
- }
-
- String displayName = null;
- // Check for writable raw contacts. If there are none, then we need to create one so user
- // can edit. For the user profile case, there is already an editable contact.
- if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
- mHasNewContact = true;
-
- // This is potentially an asynchronous call and will add deltas to list.
- selectAccountAndCreateContact();
- displayName = contact.getDisplayName();
- }
-
- // This also adds deltas to list
- // If displayName is null at this point it is simply ignored later on by the editor.
- bindEditorsForExistingContact(displayName, contact.isUserProfile(),
- mRawContacts);
-
- bindMenuItemsForPhone(contact);
}
@Override
@@ -546,7 +293,8 @@
updatedExpandedEditorsMap();
}
- private void bindEditorsForExistingContact(String displayName, boolean isUserProfile,
+ @Override
+ protected void bindEditorsForExistingContact(String displayName, boolean isUserProfile,
ImmutableList<RawContact> rawContacts) {
setEnabled(true);
mDefaultDisplayName = displayName;
@@ -584,20 +332,7 @@
bindEditors();
}
- private void bindMenuItemsForPhone(Contact contact) {
- mSendToVoicemailState = contact.isSendToVoicemail();
- mCustomRingtone = contact.getCustomRingtone();
- mArePhoneOptionsChangable = arePhoneOptionsChangable(contact);
- }
-
- private boolean arePhoneOptionsChangable(Contact contact) {
- return contact != null && !contact.isDirectoryEntry()
- && PhoneCapabilityTester.isPhone(mContext);
- }
-
- /**
- * Merges extras from the intent.
- */
+ @Override
public void setIntentExtras(Bundle extras) {
if (extras == null || extras.size() == 0) {
return;
@@ -614,64 +349,6 @@
}
}
- private void selectAccountAndCreateContact() {
- // If this is a local profile, then skip the logic about showing the accounts changed
- // activity and create a phone-local contact.
- if (mNewLocalProfile) {
- createContact(null);
- return;
- }
-
- // If there is no default account or the accounts have changed such that we need to
- // prompt the user again, then launch the account prompt.
- if (mEditorUtils.shouldShowAccountChangedNotification()) {
- Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
- mStatus = Status.SUB_ACTIVITY;
- startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED);
- } else {
- // Otherwise, there should be a default account. Then either create a local contact
- // (if default account is null) or create a contact with the specified account.
- AccountWithDataSet defaultAccount = mEditorUtils.getDefaultAccount();
- createContact(defaultAccount);
- }
- }
-
- /**
- * Create a contact by automatically selecting the first account. If there's no available
- * account, a device-local contact should be created.
- */
- private void createContact() {
- final List<AccountWithDataSet> accounts =
- AccountTypeManager.getInstance(mContext).getAccounts(true);
- // No Accounts available. Create a phone-local contact.
- if (accounts.isEmpty()) {
- createContact(null);
- return;
- }
-
- // We have an account switcher in "create-account" screen, so don't need to ask a user to
- // select an account here.
- createContact(accounts.get(0));
- }
-
- /**
- * Shows account creation screen associated with a given account.
- *
- * @param account may be null to signal a device-local contact should be created.
- */
- private void createContact(AccountWithDataSet account) {
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
- final AccountType accountType = accountTypes.getAccountTypeForAccount(account);
-
- if (accountType.getCreateContactActivityClassName() != null) {
- if (mListener != null) {
- mListener.onCustomCreateContactActivityRequested(account, mIntentExtras);
- }
- } else {
- bindEditorsForNewContact(account, accountType);
- }
- }
-
/**
* Removes a current editor ({@link #mState}) and rebinds new editor for a new account.
* Some of old data are reused with new restriction enforced by the new account.
@@ -703,7 +380,8 @@
}
}
- private void bindEditorsForNewContact(AccountWithDataSet account,
+ @Override
+ protected void bindEditorsForNewContact(AccountWithDataSet account,
final AccountType accountType) {
bindEditorsForNewContact(account, accountType, null, null);
}
@@ -748,7 +426,8 @@
bindEditors();
}
- private void bindEditors() {
+ @Override
+ protected void bindEditors() {
// bindEditors() can only bind views if there is data in mState, so immediately return
// if mState is null
if (mState.isEmpty()) {
@@ -954,7 +633,8 @@
}
}
- private void bindGroupMetaData() {
+ @Override
+ protected void bindGroupMetaData() {
if (mGroupMetaData == null) {
return;
}
@@ -1028,138 +708,6 @@
}
@Override
- public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
- inflater.inflate(R.menu.edit_contact, menu);
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
- // because the custom action bar contains the "save" button now (not the overflow menu).
- // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
- final MenuItem doneMenu = menu.findItem(R.id.menu_done);
- final MenuItem splitMenu = menu.findItem(R.id.menu_split);
- final MenuItem joinMenu = menu.findItem(R.id.menu_join);
- final MenuItem helpMenu = menu.findItem(R.id.menu_help);
- final MenuItem discardMenu = menu.findItem(R.id.menu_discard);
- final MenuItem sendToVoiceMailMenu = menu.findItem(R.id.menu_send_to_voicemail);
- final MenuItem ringToneMenu = menu.findItem(R.id.menu_set_ringtone);
- final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
- deleteMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- deleteMenu.setIcon(R.drawable.ic_delete_white_24dp);
-
- // Set visibility of menus
- doneMenu.setVisible(false);
-
- // Discard menu is only available if at least one raw contact is editable
- discardMenu.setVisible(mState != null &&
- mState.getFirstWritableRawContact(mContext) != null);
-
- // help menu depending on whether this is inserting or editing
- if (Intent.ACTION_INSERT.equals(mAction)) {
- HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_add);
- splitMenu.setVisible(false);
- joinMenu.setVisible(false);
- deleteMenu.setVisible(false);
- } else if (Intent.ACTION_EDIT.equals(mAction)) {
- HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_edit);
- // Split only if more than one raw profile and not a user profile
- splitMenu.setVisible(mState.size() > 1 && !isEditingUserProfile());
- // Cannot join a user profile
- joinMenu.setVisible(!isEditingUserProfile());
- deleteMenu.setVisible(!mDisableDeleteMenuOption);
- } else {
- // something else, so don't show the help menu
- helpMenu.setVisible(false);
- }
-
- // Hide telephony-related settings (ringtone, send to voicemail)
- // if we don't have a telephone or are editing a new contact.
- sendToVoiceMailMenu.setChecked(mSendToVoicemailState);
- sendToVoiceMailMenu.setVisible(mArePhoneOptionsChangable);
- ringToneMenu.setVisible(mArePhoneOptionsChangable);
-
- int size = menu.size();
- for (int i = 0; i < size; i++) {
- menu.getItem(i).setEnabled(mEnabled);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- case R.id.menu_done:
- return save(SaveMode.CLOSE);
- case R.id.menu_discard:
- return revert();
- case R.id.menu_delete:
- if (mListener != null) mListener.onDeleteRequested(mLookupUri);
- return true;
- case R.id.menu_split:
- return doSplitContactAction();
- case R.id.menu_join:
- return doJoinContactAction();
- case R.id.menu_set_ringtone:
- doPickRingtone();
- return true;
- case R.id.menu_send_to_voicemail:
- // Update state and save
- mSendToVoicemailState = !mSendToVoicemailState;
- item.setChecked(mSendToVoicemailState);
- final Intent intent = ContactSaveService.createSetSendToVoicemail(
- mContext, mLookupUri, mSendToVoicemailState);
- mContext.startService(intent);
- return true;
- }
-
- return false;
- }
-
- private boolean doSplitContactAction() {
- if (!hasValidState()) return false;
-
- final SplitContactConfirmationDialogFragment dialog =
- new SplitContactConfirmationDialogFragment();
- dialog.setTargetFragment(this, 0);
- dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG);
- return true;
- }
-
- private boolean doJoinContactAction() {
- if (!hasValidState()) {
- return false;
- }
-
- // If we just started creating a new contact and haven't added any data, it's too
- // early to do a join
- if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) {
- Toast.makeText(mContext, R.string.toast_join_with_empty_contact,
- Toast.LENGTH_LONG).show();
- return true;
- }
-
- return save(SaveMode.JOIN);
- }
-
- /**
- * Check if our internal {@link #mState} is valid, usually checked before
- * performing user actions.
- */
- private boolean hasValidState() {
- return mState.size() > 0;
- }
-
- /**
- * Return true if there are any edits to the current contact which need to
- * be saved.
- */
- private boolean hasPendingChanges() {
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
- return RawContactModifier.hasChanges(mState, accountTypes);
- }
-
- @Override
public boolean save(int saveMode) {
if (!hasValidState() || mStatus != Status.EDITING) {
return false;
@@ -1201,96 +749,12 @@
return true;
}
- private void doPickRingtone() {
-
- final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
- // Allow user to pick 'Default'
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
- // Show only ringtones
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
- // Allow the user to pick a silent ringtone
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
-
- final Uri ringtoneUri;
- if (mCustomRingtone != null) {
- ringtoneUri = Uri.parse(mCustomRingtone);
- } else {
- // Otherwise pick default ringtone Uri so that something is selected.
- ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
- }
-
- // Put checkmark next to the current ringtone for this contact
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
-
- // Launch!
- try {
- startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE);
- } catch (ActivityNotFoundException ex) {
- Toast.makeText(mContext, R.string.missing_app, Toast.LENGTH_SHORT).show();
- }
- }
-
- private void handleRingtonePicked(Uri pickedUri) {
- if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) {
- mCustomRingtone = null;
- } else {
- mCustomRingtone = pickedUri.toString();
- }
- Intent intent = ContactSaveService.createSetRingtone(
- mContext, mLookupUri, mCustomRingtone);
- mContext.startService(intent);
- }
-
- public static class CancelEditDialogFragment extends DialogFragment {
-
- public static void show(ContactEditorFragment fragment) {
- CancelEditDialogFragment dialog = new CancelEditDialogFragment();
- dialog.setTargetFragment(fragment, 0);
- dialog.show(fragment.getFragmentManager(), "cancelEditor");
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog dialog = new AlertDialog.Builder(getActivity())
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setMessage(R.string.cancel_confirmation_dialog_message)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int whichButton) {
- ((ContactEditorFragment)getTargetFragment()).doRevertAction();
- }
- }
- )
- .setNegativeButton(android.R.string.cancel, null)
- .create();
- return dialog;
- }
- }
-
- private boolean revert() {
- if (mState.isEmpty() || !hasPendingChanges()) {
- doRevertAction();
- } else {
- CancelEditDialogFragment.show(this);
- }
- return true;
- }
-
- private void doRevertAction() {
- // When this Fragment is closed we don't want it to auto-save
- mStatus = Status.CLOSING;
- if (mListener != null) mListener.onReverted();
- }
-
- public void doSaveAction() {
- save(SaveMode.CLOSE);
- }
-
+ @Override
public void onJoinCompleted(Uri uri) {
onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri);
}
+ @Override
public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
Uri contactLookupUri) {
if (hadChanges) {
@@ -1389,10 +853,6 @@
return false;
}
- private boolean isEditingUserProfile() {
- return mNewLocalProfile || mIsUserProfile;
- }
-
/**
* Returns the contact ID for the currently edited contact or 0 if the contact is new.
*/
@@ -1584,37 +1044,21 @@
@Override
public void onSaveInstanceState(Bundle outState) {
- outState.putParcelable(KEY_URI, mLookupUri);
- outState.putString(KEY_ACTION, mAction);
-
- if (hasValidState()) {
- // Store entities with modifications
- outState.putParcelable(KEY_EDIT_STATE, mState);
- }
- outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto);
- outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
- outState.putParcelable(KEY_CURRENT_PHOTO_URI, mCurrentPhotoUri);
+ // Joins
outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin);
outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin);
- outState.putLong(KEY_SHOW_JOIN_SUGGESTIONS, mAggregationSuggestionsRawContactId);
- outState.putBoolean(KEY_ENABLED, mEnabled);
- outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile);
- outState.putBoolean(KEY_DISABLE_DELETE_MENU_OPTION, mDisableDeleteMenuOption);
- outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
- outState.putInt(KEY_STATUS, mStatus);
- outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
- outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact);
- outState.putBoolean(KEY_IS_EDIT, mIsEdit);
- outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady);
- outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady);
- outState.putParcelableArrayList(KEY_RAW_CONTACTS,
- mRawContacts == null ?
- Lists.<RawContact>newArrayList() : Lists.newArrayList(mRawContacts));
- outState.putBoolean(KEY_SEND_TO_VOICE_MAIL_STATE, mSendToVoicemailState);
- outState.putString(KEY_CUSTOM_RINGTONE, mCustomRingtone);
- outState.putBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE, mArePhoneOptionsChangable);
+
outState.putSerializable(KEY_EXPANDED_EDITORS, mExpandedEditors);
+ // Photos
+ outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto);
+ outState.putParcelable(KEY_CURRENT_PHOTO_URI, mCurrentPhotoUri);
+ outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
+
+ // Aggregations
+ outState.putLong(KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID,
+ mAggregationSuggestionsRawContactId);
+
super.onSaveInstanceState(outState);
}
@@ -1640,33 +1084,8 @@
}
break;
}
- case REQUEST_CODE_ACCOUNTS_CHANGED: {
- // Bail if the account selector was not successful.
- if (resultCode != Activity.RESULT_OK) {
- mListener.onReverted();
- return;
- }
- // If there's an account specified, use it.
- if (data != null) {
- AccountWithDataSet account = data.getParcelableExtra(
- Intents.Insert.EXTRA_ACCOUNT);
- if (account != null) {
- createContact(account);
- return;
- }
- }
- // If there isn't an account specified, then this is likely a phone-local
- // contact, so we should continue setting up the editor by automatically selecting
- // the most appropriate account.
- createContact();
- break;
- }
- case REQUEST_CODE_PICK_RINGTONE: {
- if (data != null) {
- final Uri pickedUri = data.getParcelableExtra(
- RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
- handleRingtonePicked(pickedUri);
- }
+ default: {
+ super.onActivityResult(requestCode, resultCode, data);
break;
}
}
@@ -1751,68 +1170,6 @@
return false;
}
- /**
- * The listener for the data loader
- */
- private final LoaderManager.LoaderCallbacks<Contact> mDataLoaderListener =
- new LoaderCallbacks<Contact>() {
-
- private long mLoaderStartTime;
-
- @Override
- public Loader<Contact> onCreateLoader(int id, Bundle args) {
- mLoaderStartTime = SystemClock.elapsedRealtime();
- return new ContactLoader(mContext, mLookupUri, true);
- }
-
- @Override
- public void onLoadFinished(Loader<Contact> loader, Contact data) {
- final long loaderCurrentTime = SystemClock.elapsedRealtime();
- Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
- if (!data.isLoaded()) {
- // Item has been deleted. Close activity without saving again.
- Log.i(TAG, "No contact found. Closing activity");
- mStatus = Status.CLOSING;
- if (mListener != null) mListener.onContactNotFound();
- return;
- }
-
- mStatus = Status.EDITING;
- mLookupUri = data.getLookupUri();
- final long setDataStartTime = SystemClock.elapsedRealtime();
- setData(data);
- final long setDataEndTime = SystemClock.elapsedRealtime();
-
- Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime));
- }
-
- @Override
- public void onLoaderReset(Loader<Contact> loader) {
- }
- };
-
- /**
- * The listener for the group meta data loader for all groups.
- */
- private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener =
- new LoaderCallbacks<Cursor>() {
-
- @Override
- public CursorLoader onCreateLoader(int id, Bundle args) {
- return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI);
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- mGroupMetaData = data;
- bindGroupMetaData();
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- }
- };
-
@Override
public void onSplitContactConfirmed() {
if (mState.isEmpty()) {
diff --git a/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java b/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
index c790e0b..b4181b8 100644
--- a/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
+++ b/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
@@ -34,7 +34,11 @@
public class SplitContactConfirmationDialogFragment extends DialogFragment {
public static final String TAG = "SplitContactConfirmationDialog";
- public SplitContactConfirmationDialogFragment() {
+ public static void show(ContactEditorBaseFragment fragment) {
+ SplitContactConfirmationDialogFragment dialog = new
+ SplitContactConfirmationDialogFragment();
+ dialog.setTargetFragment(fragment, 0);
+ dialog.show(fragment.getFragmentManager(), "splitContact");
}
@Override