Merge "Start the fully expanded editor when "More fields" is clicked"
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index d04578e..713b45d 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -20,7 +20,6 @@
 import com.android.contacts.editor.ContactEditorFragment;
 import com.android.contacts.util.DialogManager;
 
-import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 
@@ -41,7 +40,8 @@
         mFragment.setListener(mFragmentListener);
 
         final String action = getIntent().getAction();
-        final Uri uri = Intent.ACTION_EDIT.equals(action) ? getIntent().getData() : null;
+        final Uri uri = ContactEditorBaseActivity.ACTION_EDIT.equals(action)
+                ? getIntent().getData() : null;
         mFragment.load(action, uri, getIntent().getExtras());
     }
 }
diff --git a/src/com/android/contacts/activities/ContactEditorBaseActivity.java b/src/com/android/contacts/activities/ContactEditorBaseActivity.java
index 46edc31..9f0a67e 100644
--- a/src/com/android/contacts/activities/ContactEditorBaseActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorBaseActivity.java
@@ -48,6 +48,20 @@
         implements DialogManager.DialogShowingViewActivity {
     protected static final String TAG = "ContactEditorActivity";
 
+    /**
+     * Intent action to edit a contact with all available field inputs displayed.
+     *
+     * Only used to open the "fully expanded" editor -- {@link ContactEditorActivity}.
+     */
+    public static final String ACTION_EDIT = "com.google.android.contacts.action.EDIT";
+
+    /**
+     * Intent action to insert a new contact with all available field inputs displayed.
+     *
+     * Only used to open the "fully expanded" editor -- {@link ContactEditorActivity}.
+     */
+    public static final String ACTION_INSERT = "com.google.android.contacts.action.INSERT";
+
     public static final String ACTION_JOIN_COMPLETED = "joinCompleted";
     public static final String ACTION_SAVE_COMPLETED = "saveCompleted";
 
@@ -111,6 +125,7 @@
              * - After Save/Close
              * - After Revert
              * - After the user has accepted an edit suggestion
+             * - After the user chooses to expand the compact editor
              */
             public static final int CLOSING = 3;
 
@@ -200,7 +215,7 @@
 
         ActionBar actionBar = getActionBar();
         if (actionBar != null) {
-            if (Intent.ACTION_EDIT.equals(action)) {
+            if (Intent.ACTION_EDIT.equals(action) || ACTION_EDIT.equals(action)) {
                 actionBar.setTitle(getResources().getString(
                         R.string.contact_editor_title_existing_contact));
             } else {
@@ -221,7 +236,7 @@
         }
 
         String action = intent.getAction();
-        if (Intent.ACTION_EDIT.equals(action)) {
+        if (Intent.ACTION_EDIT.equals(action) || Intent.ACTION_EDIT.equals(action)) {
             mFragment.setIntentExtras(intent.getExtras());
         } else if (ACTION_SAVE_COMPLETED.equals(action)) {
             mFragment.onSaveCompleted(true,
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index cfed52a..199d21f 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -19,22 +19,28 @@
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.R;
 import com.android.contacts.activities.CompactContactEditorActivity;
+import com.android.contacts.activities.ContactEditorActivity;
 import com.android.contacts.activities.ContactEditorBaseActivity;
 import com.android.contacts.common.model.AccountTypeManager;
 import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.RawContactDeltaList;
 import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.util.ImplicitIntentsUtil;
 import com.android.contacts.common.util.MaterialColorMapUtils;
 import com.android.contacts.detail.PhotoSelectionHandler;
 import com.android.contacts.editor.Editor.EditorListener;
 import com.android.contacts.util.ContactPhotoUtils;
 
 import android.app.Activity;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.Contacts;
+import android.provider.ContactsContract;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -42,9 +48,9 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
-import android.widget.Toast;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 
 /**
  * Contact editor with only the most important fields displayed initially.
@@ -351,7 +357,44 @@
 
     @Override
     public void onExpandEditor() {
-        Toast.makeText(mContext, "Not yet implemented", Toast.LENGTH_SHORT).show();
+        // Determine if this is an insert (new contact) or edit
+        final String action = getActivity().getIntent().getAction();
+        final boolean isInsert = Intent.ACTION_INSERT.equals(action)
+                || ContactEditorBaseActivity.ACTION_INSERT.equals(action);
+
+        // Prepare an Intent to start the expanded editor
+        final Intent intent = isInsert
+                ? new Intent(ContactEditorBaseActivity.ACTION_INSERT,
+                        ContactsContract.Contacts.CONTENT_URI)
+                : new Intent(ContactEditorBaseActivity.ACTION_EDIT, mLookupUri);
+        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                | Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+
+        if (isInsert) {
+            // For inserts, prevent any changes from being saved when the base fragment is destroyed
+            mStatus = Status.CLOSING;
+
+            // Pass on all the data that has been entered so far
+            ArrayList<ContentValues> contentValues = mState.get(0).getContentValues();
+            if (contentValues != null && contentValues.size() != 0) {
+                intent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contentValues);
+            }
+            // Name must be passed separately since it is skipped in RawContactModifier.parseValues
+            final StructuredNameEditorView structuredNameEditorView =
+                    getContent().getStructuredNameEditorView();
+            if (structuredNameEditorView != null) {
+                final String displayName = structuredNameEditorView.getDisplayName();
+                if (!TextUtils.isEmpty(displayName)) {
+                    intent.putExtra(ContactsContract.Intents.Insert.NAME, displayName);
+                }
+            }
+            getActivity().finish();
+        } else {
+            // Whatever is in the form will be saved when the hosting activity is finished
+            save(SaveMode.RELOAD);
+        }
+
+        ImplicitIntentsUtil.startActivityInApp(getActivity(), intent);
     }
 
     private CompactRawContactsEditorView getContent() {
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index 48e655b..1287d47 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -119,7 +119,6 @@
         mMoreFields.setOnClickListener(this);
     }
 
-
     @Override
     public void onClick(View view) {
         if (view.getId() == R.id.more_fields && mListener != null ) {
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 3ca492b..57905d1 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -97,6 +97,14 @@
     protected static final int LOADER_DATA = 1;
     protected static final int LOADER_GROUPS = 2;
 
+    private static final List<String> VALID_INTENT_ACTIONS = new ArrayList() {{
+        add(Intent.ACTION_EDIT);
+        add(Intent.ACTION_INSERT);
+        add(ContactEditorBaseActivity.ACTION_EDIT);
+        add(ContactEditorBaseActivity.ACTION_INSERT);
+        add(ContactEditorBaseActivity.ACTION_SAVE_COMPLETED);
+    }};
+
     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";
@@ -477,7 +485,8 @@
             // 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)) {
+            if (Intent.ACTION_EDIT.equals(mAction) ||
+                    ContactEditorBaseActivity.ACTION_EDIT.equals(mAction)) {
                 // Either...
                 // 1) orientation change but load never finished.
                 // or
@@ -491,9 +500,11 @@
 
         // Handle initial actions only when existing state missing
         if (savedInstanceState == null) {
-            if (Intent.ACTION_EDIT.equals(mAction)) {
+            if (Intent.ACTION_EDIT.equals(mAction) ||
+                    ContactEditorBaseActivity.ACTION_EDIT.equals(mAction)) {
                 mIsEdit = true;
-            } else if (Intent.ACTION_INSERT.equals(mAction)) {
+            } else if (Intent.ACTION_INSERT.equals(mAction) ||
+                    ContactEditorBaseActivity.ACTION_INSERT.equals(mAction)) {
                 mHasNewContact = true;
                 final Account account = mIntentExtras == null ? null :
                         (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
@@ -519,13 +530,11 @@
      * @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)) {
+        if (VALID_INTENT_ACTIONS.contains(action)) {
             return;
         }
-        throw new IllegalArgumentException("Unknown Action String " + action +
-                ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT + " or " +
-                ContactEditorBaseActivity.ACTION_SAVE_COMPLETED);
+        throw new IllegalArgumentException(
+                "Unknown action " + action + "; Supported actions: " + VALID_INTENT_ACTIONS);
     }
 
     @Override
@@ -705,12 +714,14 @@
                 mState.getFirstWritableRawContact(mContext) != null);
 
         // help menu depending on whether this is inserting or editing
-        if (Intent.ACTION_INSERT.equals(mAction)) {
+        if (Intent.ACTION_INSERT.equals(mAction) ||
+                ContactEditorBaseActivity.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)) {
+        } else if (Intent.ACTION_EDIT.equals(mAction) ||
+                ContactEditorBaseActivity.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());
@@ -986,8 +997,10 @@
     protected void saveDefaultAccountIfNecessary() {
         // Verify that this is a newly created contact, that the contact is composed of only
         // 1 raw contact, and that the contact is not a user profile.
-        if (!Intent.ACTION_INSERT.equals(mAction) && mState.size() == 1 &&
-                !isEditingUserProfile()) {
+        if (!Intent.ACTION_INSERT.equals(mAction)
+                && !ContactEditorBaseActivity.ACTION_INSERT.equals(mAction)
+                && mState.size() == 1
+                && !isEditingUserProfile()) {
             return;
         }
 
@@ -1294,8 +1307,9 @@
 
                     // If this was in INSERT, we are changing into an EDIT now.
                     // If it already was an EDIT, we are changing to the new Uri now
+                    // Either way, open the editor with all input fields displayed.
                     mState = new RawContactDeltaList();
-                    load(Intent.ACTION_EDIT, contactLookupUri, null);
+                    load(ContactEditorBaseActivity.ACTION_EDIT, contactLookupUri, null);
                     mStatus = Status.LOADING;
                     getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener);
                 }
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index b24f7f1..209f2d3 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -214,6 +214,13 @@
         super.setValue(0, name);
     }
 
+    /**
+     * Returns the display name from the underlying ValuesDelta.
+     */
+    public String getDisplayName() {
+        return getValues().getDisplayName();
+    }
+
     @Override
     protected Parcelable onSaveInstanceState() {
         SavedState state = new SavedState(super.onSaveInstanceState());
diff --git a/src/com/android/contacts/interactions/GroupCreationDialogFragment.java b/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
index b2860ea..e998688 100644
--- a/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
+++ b/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
@@ -23,6 +23,7 @@
 
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.R;
+import com.android.contacts.activities.ContactEditorBaseActivity;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 
 /**
@@ -94,6 +95,6 @@
         activity.startService(ContactSaveService.createNewGroupIntent(activity,
                 new AccountWithDataSet(accountName, accountType, dataSet), groupLabel,
                 null /* no new members to add */,
-                activity.getClass(), Intent.ACTION_EDIT));
+                activity.getClass(), ContactEditorBaseActivity.ACTION_EDIT));
     }
 }