Merge "Hide tabs in PeopleActivity"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6d0c48c..b9616bf 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -257,6 +257,10 @@
             </intent-filter>
         </activity>
 
+        <!-- Displays the members of a group in a list -->
+        <activity android:name=".activities.GroupMembersActivity"
+            android:theme="@style/ContactPickerTheme"/>
+
         <!-- Views the details of a single group -->
         <activity android:name=".activities.GroupDetailActivity"
             android:label=""
diff --git a/src/com/android/contacts/GroupListLoader.java b/src/com/android/contacts/GroupListLoader.java
index 2589c9b..d43f561 100644
--- a/src/com/android/contacts/GroupListLoader.java
+++ b/src/com/android/contacts/GroupListLoader.java
@@ -47,9 +47,13 @@
     private static final Uri GROUP_LIST_URI = Groups.CONTENT_SUMMARY_URI;
 
     public GroupListLoader(Context context) {
-        super(context, GROUP_LIST_URI, COLUMNS, Groups.ACCOUNT_TYPE + " NOT NULL AND "
-                + Groups.ACCOUNT_NAME + " NOT NULL AND " + Groups.AUTO_ADD + "=0 AND " +
-                Groups.FAVORITES + "=0 AND " + Groups.DELETED + "=0", null,
+        super(context,
+                GROUP_LIST_URI,
+                COLUMNS,
+                Groups.ACCOUNT_TYPE + " NOT NULL AND " +
+                        Groups.ACCOUNT_NAME + " NOT NULL AND " + Groups.AUTO_ADD + "=0 AND " +
+                        Groups.FAVORITES + "=0 AND " + Groups.DELETED + "=0",
+                null,
                 Groups.ACCOUNT_TYPE + ", " + Groups.ACCOUNT_NAME + ", " + Groups.DATA_SET + ", " +
                 Groups.TITLE + " COLLATE LOCALIZED ASC");
     }
diff --git a/src/com/android/contacts/activities/GroupEditorActivity.java b/src/com/android/contacts/activities/GroupEditorActivity.java
index b204418..d48ed97 100644
--- a/src/com/android/contacts/activities/GroupEditorActivity.java
+++ b/src/com/android/contacts/activities/GroupEditorActivity.java
@@ -146,7 +146,7 @@
         @Override
         public void onSaveFinished(int resultCode, Intent resultIntent) {
             if (resultIntent != null) {
-                Intent intent = new Intent(GroupEditorActivity.this, GroupDetailActivity.class);
+                Intent intent = new Intent(GroupEditorActivity.this, GroupMembersActivity.class);
                 intent.setData(resultIntent.getData());
                 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                 startActivity(intent);
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index c6ad4a7..e13bcd6 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -25,16 +25,14 @@
 import com.android.contacts.R;
 import com.android.contacts.common.util.ImplicitIntentsUtil;
 import com.android.contacts.group.GroupMembersListFragment;
-import com.android.contacts.group.GroupMembersListFragment.GroupMembersCallbacks;
+import com.android.contacts.group.GroupMembersListFragment.GroupMembersListCallbacks;
 import com.android.contacts.quickcontact.QuickContactActivity;
 
 /** Displays the members of a group. */
-public class GroupMembersActivity extends ContactsActivity implements GroupMembersCallbacks {
+public class GroupMembersActivity extends ContactsActivity implements GroupMembersListCallbacks {
 
     private static final String TAG_GROUP_MEMBERS = "group_members";
 
-    public static final String EXTRA_MEMBERS_COUNT = "membersCount";
-
     private GroupMembersListFragment mFragment;
 
     @Override
@@ -59,7 +57,6 @@
                     .commit();
         }
         mFragment.setGroupUri(getIntent().getData());
-        mFragment.setMembersCount(getIntent().getIntExtra(EXTRA_MEMBERS_COUNT, -1));
         mFragment.setCallbacks(this);
     }
 
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index e2c06dd..4a09cd1 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -900,8 +900,7 @@
                     : getString(R.string.group_name_menu_item, groupListItem.getTitle(),
                             groupListItem.getMemberCount());
             final MenuItem menuItem = menu.add(R.id.nav_groups, Menu.NONE, Menu.NONE, title);
-            menuItem.setIntent(GroupUtil.createViewGroupIntent(
-                    this, groupListItem.getGroupId(), groupListItem.getMemberCount()));
+            menuItem.setIntent(GroupUtil.createViewGroupIntent(this, groupListItem.getGroupId()));
         }
 
         // Create a menu item to add new groups
diff --git a/src/com/android/contacts/group/GroupMembersListFragment.java b/src/com/android/contacts/group/GroupMembersListFragment.java
index 442f88d..b8dad5e 100644
--- a/src/com/android/contacts/group/GroupMembersListFragment.java
+++ b/src/com/android/contacts/group/GroupMembersListFragment.java
@@ -24,6 +24,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.provider.ContactsContract.Groups;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -33,6 +34,7 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.contacts.GroupListLoader;
 import com.android.contacts.GroupMetaDataLoader;
 import com.android.contacts.R;
 import com.android.contacts.common.list.ContactEntryListFragment;
@@ -46,13 +48,12 @@
     private static final String TAG = "GroupMembersList";
 
     private static final String KEY_GROUP_URI = "groupUri";
-    private static final String KEY_MEMBERS_COUNT = "membersCount";
     private static final String KEY_GROUP_METADATA = "groupMetadata";
 
     private static final int LOADER_GROUP_METADATA = 0;
+    private static final int LOADER_GROUP_LIST_DETAILS = 1;
 
-    /** The listener for the group metadata loader. */
-    private final LoaderCallbacks<Cursor> mGroupMetadatCallbacks = new LoaderCallbacks<Cursor>() {
+    private final LoaderCallbacks<Cursor> mGroupMetadataCallbacks = new LoaderCallbacks<Cursor>() {
 
         @Override
         public CursorLoader onCreateLoader(int id, Bundle args) {
@@ -81,7 +82,8 @@
                             mGroupMetadata.accountType, mGroupMetadata.dataSet);
                     mGroupMetadata.editable = accountType.isGroupMembershipEditable();
 
-                    onGroupMetadataLoaded();
+                    getLoaderManager().restartLoader(LOADER_GROUP_LIST_DETAILS, null,
+                            mGroupListDetailsCallbacks);
                 }
             }
         }
@@ -90,6 +92,41 @@
         public void onLoaderReset(Loader<Cursor> loader) {}
     };
 
+    private final LoaderCallbacks<Cursor> mGroupListDetailsCallbacks =
+            new LoaderCallbacks<Cursor>() {
+
+        @Override
+        public CursorLoader onCreateLoader(int id, Bundle args) {
+            final GroupListLoader groupListLoader = new GroupListLoader(getContext());
+
+            // TODO(wjang): modify GroupListLoader to accept this selection criteria more naturally
+            groupListLoader.setSelection(groupListLoader.getSelection()
+                    + " AND " + Groups._ID + "=?");
+
+            final String[] selectionArgs = new String[1];
+            selectionArgs[0] = Long.toString(mGroupMetadata.groupId);
+            groupListLoader.setSelectionArgs(selectionArgs);
+
+            return groupListLoader;
+        }
+
+        @Override
+        public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+            if (cursor == null || cursor.isClosed()) {
+                Log.e(TAG, "Failed to load group list details");
+                return;
+            }
+            if (cursor.moveToNext()) {
+                mGroupMetadata.memberCount = cursor.getInt(GroupListLoader.MEMBER_COUNT);
+            }
+
+            onGroupMetadataLoaded();
+        }
+
+        @Override
+        public void onLoaderReset(Loader<Cursor> loader) {}
+    };
+
     private static final class GroupMetadata implements Parcelable {
 
         public static final Creator<GroupMetadata> CREATOR = new Creator<GroupMetadata>() {
@@ -109,6 +146,7 @@
         String groupName;
         boolean readOnly;
         boolean editable;
+        int memberCount = -1;
 
         GroupMetadata() {
         }
@@ -130,6 +168,7 @@
             dest.writeString(groupName);
             dest.writeInt(readOnly ? 1 : 0);
             dest.writeInt(editable ? 1 : 0);
+            dest.writeInt(memberCount);
         }
 
         private void readFromParcel(Parcel source) {
@@ -139,6 +178,7 @@
             groupName = source.readString();
             readOnly = source.readInt() == 1;
             editable = source.readInt() == 1;
+            memberCount = source.readInt();
         }
 
         @Override
@@ -149,12 +189,13 @@
                     " groupName=" + groupName +
                     " readOnly=" + readOnly +
                     " editable=" + editable +
+                    " memberCount=" + memberCount +
                     "]";
         }
     }
 
     /** Callbacks for hosts of {@link GroupMembersListFragment}. */
-    public interface GroupMembersCallbacks {
+    public interface GroupMembersListCallbacks {
 
         /** Invoked when the user hits back in the action bar. */
         void onHomePressed();
@@ -170,8 +211,8 @@
     }
 
     private Uri mGroupUri;
-    private int mMembersCount;
-    private GroupMembersCallbacks mCallbacks;
+
+    private GroupMembersListCallbacks mCallbacks;
 
     private GroupMetadata mGroupMetadata;
 
@@ -190,12 +231,8 @@
         mGroupUri = groupUri;
     }
 
-    public void setMembersCount(int membersCount) {
-        mMembersCount = membersCount;
-    }
-
     /** Sets a listener for group member click events. */
-    public void setCallbacks(GroupMembersCallbacks callbacks) {
+    public void setCallbacks(GroupMembersListCallbacks callbacks) {
         mCallbacks = callbacks;
     }
 
@@ -204,7 +241,6 @@
         super.onCreate(savedState);
         if (savedState != null) {
             mGroupUri = savedState.getParcelable(KEY_GROUP_URI);
-            mMembersCount = savedState.getInt(KEY_MEMBERS_COUNT);
             mGroupMetadata = savedState.getParcelable(KEY_GROUP_METADATA);
         }
     }
@@ -213,14 +249,13 @@
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         outState.putParcelable(KEY_GROUP_URI, mGroupUri);
-        outState.putInt(KEY_MEMBERS_COUNT, mMembersCount);
         outState.putParcelable(KEY_GROUP_METADATA, mGroupMetadata);
     }
 
     @Override
     protected void startLoading() {
         if (mGroupMetadata == null) {
-            getLoaderManager().restartLoader(LOADER_GROUP_METADATA, null, mGroupMetadatCallbacks);
+            getLoaderManager().restartLoader(LOADER_GROUP_METADATA, null, mGroupMetadataCallbacks);
         } else {
             onGroupMetadataLoaded();
         }
@@ -291,13 +326,14 @@
     private void bindMembersCount() {
         final View accountFilterContainer = getView().findViewById(
                 R.id.account_filter_header_container);
-        if (mMembersCount >= 0) {
+        if (mGroupMetadata.memberCount >= 0) {
             accountFilterContainer.setVisibility(View.VISIBLE);
 
             final TextView accountFilterHeader = (TextView) accountFilterContainer.findViewById(
                     R.id.account_filter_header);
             accountFilterHeader.setText(getResources().getQuantityString(
-                    R.plurals.group_members_count, mMembersCount, mMembersCount));
+                    R.plurals.group_members_count, mGroupMetadata.memberCount,
+                    mGroupMetadata.memberCount));
         } else {
             accountFilterContainer.setVisibility(View.GONE);
         }
diff --git a/src/com/android/contacts/group/GroupUtil.java b/src/com/android/contacts/group/GroupUtil.java
index f8e42ee..6d6fec1 100644
--- a/src/com/android/contacts/group/GroupUtil.java
+++ b/src/com/android/contacts/group/GroupUtil.java
@@ -24,7 +24,6 @@
 import android.provider.ContactsContract.Groups;
 
 import com.android.contacts.GroupListLoader;
-import com.android.contacts.activities.GroupDetailActivity;
 import com.android.contacts.activities.GroupEditorActivity;
 import com.android.contacts.activities.GroupMembersActivity;
 import com.google.common.base.Objects;
@@ -78,10 +77,9 @@
     }
 
     /** Returns an Intent to view the details of the group identified by the given Uri. */
-    public static Intent createViewGroupIntent(Context context, long groupId, int membersCount) {
-        final Intent intent = new Intent(context, GroupDetailActivity.class);
+    public static Intent createViewGroupIntent(Context context, long groupId) {
+        final Intent intent = new Intent(context, GroupMembersActivity.class);
         intent.setData(getGroupUriFromId(groupId));
-        intent.putExtra(GroupMembersActivity.EXTRA_MEMBERS_COUNT, membersCount);
         return intent;
     }
 
diff --git a/src/com/android/contacts/group/GroupsFragment.java b/src/com/android/contacts/group/GroupsFragment.java
index 15529c7..be1b44a 100644
--- a/src/com/android/contacts/group/GroupsFragment.java
+++ b/src/com/android/contacts/group/GroupsFragment.java
@@ -47,15 +47,12 @@
         void onGroupsLoaded(List<GroupListItem> groupListItems);
     }
 
-    /**
-     * Group meta data loader listener.
-     */
-    private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener =
+    private final LoaderManager.LoaderCallbacks<Cursor> mGroupListLoaderListener =
             new LoaderManager.LoaderCallbacks<Cursor>() {
 
                 @Override
                 public CursorLoader onCreateLoader(int id, Bundle args) {
-                    return new GroupListLoader(mContext);
+                    return new GroupListLoader(getActivity());
                 }
 
                 @Override
@@ -75,25 +72,12 @@
                 }
             };
 
-    private Context mContext;
     private List<GroupListItem> mGroupListItems = new ArrayList<>();
     private GroupsListener mListener;
 
     @Override
-    public void onAttach(Context context) {
-        super.onAttach(context);
-        mContext = context;
-    }
-
-    @Override
-    public void onDetach() {
-        super.onDetach();
-        mContext = null;
-    }
-
-    @Override
     public void onStart() {
-        getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener);
+        getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupListLoaderListener);
         super.onStart();
     }
 
diff --git a/src/com/android/contacts/interactions/JoinContactsDialogFragment.java b/src/com/android/contacts/interactions/JoinContactsDialogFragment.java
index 205e18e..37ced3f 100644
--- a/src/com/android/contacts/interactions/JoinContactsDialogFragment.java
+++ b/src/com/android/contacts/interactions/JoinContactsDialogFragment.java
@@ -36,7 +36,9 @@
  */
 public class JoinContactsDialogFragment extends DialogFragment {
 
-    private static final String FRAGMENT_TAG = "joinDialog";
+    public static final String FRAGMENT_TAG = "joinDialog";
+    public static final String KEY_POSITION = "position";
+
     private static final String KEY_CONTACT_IDS = "contactIds";
 
     public interface JoinContactsListener {
@@ -50,10 +52,22 @@
         newFragment.show(ft, FRAGMENT_TAG);
     }
 
-    private static JoinContactsDialogFragment newInstance(TreeSet<Long> contactIds) {
+    public static JoinContactsDialogFragment newInstance(TreeSet<Long> contactIds) {
+        return newInstance(contactIds, -1);
+    }
+
+    /**
+     * Creates a new instance of {@link JoinContactsDialogFragment} with passed in arguments.
+     * 
+     * Position parameter is passed back to target fragment if this instance of the join dialog
+     * was launched from a list fragment that needs to know which item position in the list
+     * the dialog was launched from.
+     */
+    public static JoinContactsDialogFragment newInstance(TreeSet<Long> contactIds, int position) {
         final JoinContactsDialogFragment fragment = new JoinContactsDialogFragment();
         Bundle arguments = new Bundle();
         arguments.putSerializable(KEY_CONTACT_IDS, contactIds);
+        arguments.putInt(KEY_POSITION, position);
         fragment.setArguments(arguments);
         return fragment;
     }
@@ -101,6 +115,11 @@
     private void notifyListener() {
         if (getActivity() instanceof JoinContactsListener) {
             ((JoinContactsListener) getActivity()).onContactsJoined();
+        } else if (getTargetFragment() != null) {
+            final Intent intent = new Intent()
+                    .putExtra(KEY_POSITION, getArguments().getInt(KEY_POSITION));
+            getTargetFragment().onActivityResult(getTargetRequestCode(),
+                    Activity.RESULT_OK, intent);
         }
     }