Warn about saving pending changes before unlinking

Also, remove unchanged new raw contacts that were
created to edit read-only contacts before unlinking.

Bug 25314004

Change-Id: Id75083456cd24fc1b06e489380614172bd370ad4
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0193843..53579bd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -147,6 +147,9 @@
     <!-- Confirmation dialog for unlinking contacts into multiple instances [CHAR LIMIT=NONE] -->
     <string name="splitConfirmation">This contact will be unlinked into multiple contacts.</string>
 
+    <!-- Confirmation dialog for unlinking contacts into multiple instances when there are also unsaved changes for the current contact. [CHAR LIMIT=NONE] -->
+    <string name="splitConfirmationWithPendingChanges">There are unsaved changes. Do you want to save them before unlinking this contact into multiple contacts?</string>
+
     <!-- Title of the confirmation dialog for joining contacts when there are unsaved changes. [CHAR LIMIT=40] -->
     <string name="joinConfirmation_title">Link contact?</string>
 
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index bd3f91d..e17b2cd 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -85,6 +85,7 @@
 
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -860,7 +861,7 @@
     }
 
     @Override
-    public void onSplitContactConfirmed() {
+    public void onSplitContactConfirmed(boolean hasPendingChanges) {
         if (mState.isEmpty()) {
             // This may happen when this Fragment is recreated by the system during users
             // confirming the split action (and thus this method is called just before onCreate()),
@@ -870,6 +871,17 @@
             return;
         }
 
+        if (!hasPendingChanges && mHasNewContact) {
+            // If the user didn't add anything new, we don't want to split out the newly created
+            // raw contact into a name-only contact so remove them.
+            final Iterator<RawContactDelta> iterator = mState.iterator();
+            while (iterator.hasNext()) {
+                final RawContactDelta rawContactDelta = iterator.next();
+                if (rawContactDelta.getRawContactId() < 0) {
+                    iterator.remove();
+                }
+            }
+        }
         mState.markRawContactsForSplitting();
         save(SaveMode.SPLIT);
     }
@@ -877,7 +889,7 @@
     private boolean doSplitContactAction() {
         if (!hasValidState()) return false;
 
-        SplitContactConfirmationDialogFragment.show(this);
+        SplitContactConfirmationDialogFragment.show(this, hasPendingChanges());
         return true;
     }
 
diff --git a/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java b/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
index b4181b8..521a689 100644
--- a/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
+++ b/src/com/android/contacts/editor/SplitContactConfirmationDialogFragment.java
@@ -32,34 +32,59 @@
  * Does not split the contact itself.
  */
 public class SplitContactConfirmationDialogFragment extends DialogFragment {
-    public static final String TAG = "SplitContactConfirmationDialog";
 
-    public static void show(ContactEditorBaseFragment fragment) {
-        SplitContactConfirmationDialogFragment dialog = new
+    private static final String ARG_HAS_PENDING_CHANGES = "hasPendingChanges";
+
+    /**
+     * Callbacks for the dialog host.
+     */
+    public interface Listener {
+
+        /**
+         * Invoked after the user has confirmed that they want to proceed with the split.
+         *
+         * @param hasPendingChanges whether there are unsaved changes in the underlying contact
+         *         that should be saved before the split.
+         */
+        void onSplitContactConfirmed(boolean hasPendingChanges);
+    }
+
+    public static void show(ContactEditorBaseFragment fragment, boolean hasPendingChanges) {
+        final Bundle args = new Bundle();
+        args.putBoolean(ARG_HAS_PENDING_CHANGES, hasPendingChanges);
+
+        final SplitContactConfirmationDialogFragment dialog = new
                 SplitContactConfirmationDialogFragment();
         dialog.setTargetFragment(fragment, 0);
+        dialog.setArguments(args);
         dialog.show(fragment.getFragmentManager(), "splitContact");
     }
 
+    private boolean mHasPendingChanges;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mHasPendingChanges = getArguments().getBoolean(ARG_HAS_PENDING_CHANGES);
+    }
+
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         builder.setTitle(R.string.splitConfirmation_title);
         builder.setIconAttribute(android.R.attr.alertDialogIcon);
-        builder.setMessage(R.string.splitConfirmation);
+        builder.setMessage(mHasPendingChanges
+                ? R.string.splitConfirmationWithPendingChanges
+                : R.string.splitConfirmation);
         builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 final Listener targetListener = (Listener) getTargetFragment();
-                targetListener.onSplitContactConfirmed();
+                targetListener.onSplitContactConfirmed(mHasPendingChanges);
             }
         });
         builder.setNegativeButton(android.R.string.cancel, null);
         builder.setCancelable(false);
         return builder.create();
     }
-
-    public interface Listener {
-        void onSplitContactConfirmed();
-    }
 }