Incremental work on the group edit flow
* Extract group metadata class from members list fragment
* Move metadata loading up to the Activity so it can be
shared between the members list and editor fragments
* Move options menu creation in the members list fragment
up to the Activity and remove the obsolete members list
callbacks (also rename the members list callbacks
interface to "Listener" to match the rest of Contacts).
* Use a custom ViewPager that disabled swipes to move
between the members list and editor fragments (also added
a TODO to rename GroupMembersListActivity since it houses
the editor now too).
* Update the group editor fragment to have group metadata
passed in as an argument rather than loading it internally
since we need it for the group members list view and it's
already being loaded by the group members activity.
Bug 28707265
Bug 18641067
Change-Id: If662abd720533827e3e719fde4dd10cdfb1ba64e
diff --git a/res/layout/group_members_activity.xml b/res/layout/group_members_activity.xml
index 387fdd2..eecec50 100644
--- a/res/layout/group_members_activity.xml
+++ b/res/layout/group_members_activity.xml
@@ -25,4 +25,10 @@
layout="@layout/people_activity_toolbar"
android:id="@+id/toolbar_parent" />
+ <com.android.contacts.widget.NoSwipeViewPager
+ android:id="@+id/view_pager"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1"/>
+
</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/edit_group.xml b/res/menu/edit_group.xml
index b94563f..ad17b80 100644
--- a/res/menu/edit_group.xml
+++ b/res/menu/edit_group.xml
@@ -17,12 +17,10 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_save"
- android:showAsAction="always"
+ android:showAsAction="ifRoom"
android:icon="@drawable/ic_done_wht_24dp"
android:title="@string/menu_save" />
<item
android:id="@+id/menu_discard"
- android:alphabeticShortcut="q"
- android:title="@string/menu_discard"
- android:showAsAction="withText" />
+ android:title="@string/menu_discard" />
</menu>
diff --git a/src/com/android/contacts/activities/GroupEditorActivity.java b/src/com/android/contacts/activities/GroupEditorActivity.java
index 8a285a7..5f2789e 100644
--- a/src/com/android/contacts/activities/GroupEditorActivity.java
+++ b/src/com/android/contacts/activities/GroupEditorActivity.java
@@ -30,6 +30,7 @@
import com.android.contacts.quickcontact.QuickContactActivity;
import com.android.contacts.util.DialogManager;
+// TODO(wjang): it longer works. will be deleted shortly
public class GroupEditorActivity extends ContactsActivity
implements DialogManager.DialogShowingViewActivity {
@@ -63,13 +64,13 @@
mFragment = (GroupEditorFragment) getFragmentManager().findFragmentById(
R.id.group_editor_fragment);
mFragment.setListener(mFragmentListener);
- mFragment.setContentResolver(getContentResolver());
+ // mFragment.setContentResolver(getContentResolver());
// NOTE The fragment will restore its state by itself after orientation changes, so
// we need to do this only for a new instance.
if (savedState == null) {
Uri uri = Intent.ACTION_EDIT.equals(action) ? getIntent().getData() : null;
- mFragment.load(action, uri, getIntent().getExtras());
+ // mFragment.load(action, uri, getIntent().getExtras());
}
}
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index 5a1f8e2..2221820 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -15,53 +15,241 @@
*/
package com.android.contacts.activities;
+import android.app.Fragment;
import android.app.FragmentManager;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.CursorLoader;
import android.content.Intent;
+import android.content.Loader;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
import android.widget.Toast;
import com.android.contacts.AppCompatContactsActivity;
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.GroupListLoader;
+import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.util.ImplicitIntentsUtil;
+import com.android.contacts.group.GroupEditorFragment;
import com.android.contacts.group.GroupMembersListFragment;
-import com.android.contacts.group.GroupMembersListFragment.GroupMembersListCallbacks;
+import com.android.contacts.group.GroupMetadata;
+import com.android.contacts.group.GroupUtil;
+import com.android.contacts.interactions.GroupDeletionDialogFragment;
import com.android.contacts.list.ContactsRequest;
import com.android.contacts.list.MultiSelectContactsListFragment;
import com.android.contacts.quickcontact.QuickContactActivity;
-/** Displays the members of a group. */
+/**
+ * Displays the members of a group and allows the user to edit it.
+ */
+// TODO(wjang): rename it to GroupActivity since it does both display and edit now.
public class GroupMembersActivity extends AppCompatContactsActivity implements
ActionBarAdapter.Listener,
MultiSelectContactsListFragment.OnCheckBoxListActionListener,
- GroupMembersListCallbacks {
+ GroupMembersListFragment.GroupMembersListListener,
+ GroupEditorFragment.Listener {
- private static final String TAG_GROUP_MEMBERS = "group_members";
+ private static final String TAG = "GroupMembersActivity";
+
+ private static final boolean DEBUG = false;
+
+ 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;
+
+ private static final int FRAGMENT_MEMBERS_LIST = -1;
+ private static final int FRAGMENT_EDITOR = -2;
public static final String ACTION_SAVE_COMPLETED = "saveCompleted";
- private GroupMembersListFragment mFragment;
+ private class GroupPagerAdapter extends FragmentPagerAdapter {
+
+ public GroupPagerAdapter(FragmentManager fragmentManager) {
+ super(fragmentManager);
+ }
+
+ @Override
+ public int getCount() {
+ return mIsInsertAction ? 1 : 2;
+ }
+
+ public Fragment getItem(int position) {
+ if (mIsInsertAction) {
+ switch (position) {
+ case 0:
+ mEditorFragment = GroupEditorFragment.newInstance(
+ Intent.ACTION_INSERT, mGroupMetadata, getIntent().getExtras());
+ return mEditorFragment;
+ }
+ throw new IllegalStateException("Unhandled position " + position);
+ } else {
+ switch (position) {
+ case 0:
+ mMembersListFragment = GroupMembersListFragment.newInstance(mGroupMetadata);
+ return mMembersListFragment;
+ case 1:
+ // TODO: double check what intent extras need to be supported
+ mEditorFragment = GroupEditorFragment.newInstance(
+ Intent.ACTION_EDIT, mGroupMetadata, getIntent().getExtras());
+ return mEditorFragment;
+ }
+ throw new IllegalStateException("Unhandled position " + position);
+ }
+ }
+
+ private boolean isCurrentItem(int fragment) {
+ if (mIsInsertAction) {
+ return FRAGMENT_EDITOR == fragment;
+ }
+ int currentItem = mViewPager.getCurrentItem();
+ switch (fragment) {
+ case FRAGMENT_MEMBERS_LIST:
+ return currentItem == 0;
+ case FRAGMENT_EDITOR:
+ return currentItem == 1;
+ }
+ return false;
+ }
+
+ private void setCurrentItem(int fragment) {
+ if (mIsInsertAction) {
+ switch (fragment) {
+ case FRAGMENT_EDITOR:
+ mViewPager.setCurrentItem(0);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported fragment " + fragment);
+ }
+ } else {
+ switch (fragment) {
+ case FRAGMENT_MEMBERS_LIST:
+ mViewPager.setCurrentItem(0);
+ break;
+ case FRAGMENT_EDITOR:
+ mViewPager.setCurrentItem(1);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported fragment " + fragment);
+ }
+ }
+ }
+ }
+
+ /** Step 1 of loading group metadata. */
+ private final LoaderCallbacks<Cursor> mGroupMetadataCallbacks = new LoaderCallbacks<Cursor>() {
+
+ @Override
+ public CursorLoader onCreateLoader(int id, Bundle args) {
+ return new GroupMetaDataLoader(GroupMembersActivity.this, mGroupUri);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ if (cursor == null || cursor.isClosed()) {
+ Log.e(TAG, "Failed to load group metadata");
+ return;
+ }
+ if (cursor.moveToNext()) {
+ final boolean deleted = cursor.getInt(GroupMetaDataLoader.DELETED) == 1;
+ if (!deleted) {
+ mGroupMetadata = new GroupMetadata();
+ mGroupMetadata.uri = mGroupUri;
+ mGroupMetadata.accountName = cursor.getString(GroupMetaDataLoader.ACCOUNT_NAME);
+ mGroupMetadata.accountType = cursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
+ mGroupMetadata.dataSet = cursor.getString(GroupMetaDataLoader.DATA_SET);
+ mGroupMetadata.groupId = cursor.getLong(GroupMetaDataLoader.GROUP_ID);
+ mGroupMetadata.groupName = cursor.getString(GroupMetaDataLoader.TITLE);
+ mGroupMetadata.readOnly = cursor.getInt(GroupMetaDataLoader.IS_READ_ONLY) == 1;
+
+ final AccountTypeManager accountTypeManager =
+ AccountTypeManager.getInstance(GroupMembersActivity.this);
+ final AccountType accountType = accountTypeManager.getAccountType(
+ mGroupMetadata.accountType, mGroupMetadata.dataSet);
+ mGroupMetadata.editable = accountType.isGroupMembershipEditable();
+
+ getLoaderManager().restartLoader(LOADER_GROUP_LIST_DETAILS, null,
+ mGroupListCallbacks);
+ }
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {}
+ };
+
+ /** Step 2 of loading group metadata. */
+ private final LoaderCallbacks<Cursor> mGroupListCallbacks = new LoaderCallbacks<Cursor>() {
+
+ @Override
+ public CursorLoader onCreateLoader(int id, Bundle args) {
+ final GroupListLoader groupListLoader = new GroupListLoader(GroupMembersActivity.this);
+
+ // TODO(wjang): modify GroupListLoader to accept this selection criteria more naturally
+ groupListLoader.setSelection(groupListLoader.getSelection()
+ + " AND " + ContactsContract.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 ActionBarAdapter mActionBarAdapter;
+ private ViewPager mViewPager;
+
+ private GroupPagerAdapter mPagerAdapter;
+
+ private Uri mGroupUri;
+ private GroupMetadata mGroupMetadata;
+
+ private GroupMembersListFragment mMembersListFragment;
+ private GroupEditorFragment mEditorFragment;
+
+ private boolean mIsInsertAction;
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
- setContentView(R.layout.group_members_activity);
+ mIsInsertAction = Intent.ACTION_INSERT.equals(getIntent().getAction());
- // Add the group members list fragment
- final FragmentManager fragmentManager = getFragmentManager();
- mFragment = (GroupMembersListFragment) fragmentManager.findFragmentByTag(TAG_GROUP_MEMBERS);
- if (mFragment == null) {
- mFragment = new GroupMembersListFragment();
- fragmentManager.beginTransaction()
- .add(R.id.fragment_container, mFragment, TAG_GROUP_MEMBERS)
- .commit();
+ mGroupUri = getIntent().getData();
+ if (savedState != null) {
+ mGroupMetadata = savedState.getParcelable(KEY_GROUP_METADATA);
}
- mFragment.setGroupUri(getIntent().getData());
- mFragment.setCallbacks(this);
- mFragment.setCheckBoxListListener(this);
+
+ // Setup the view
+ setContentView(R.layout.group_members_activity);
+ mViewPager = (ViewPager) findViewById(R.id.view_pager);
// Set up the action bar
final Toolbar toolbar = getView(R.id.toolbar);
@@ -76,65 +264,167 @@
}
@Override
- protected void onNewIntent(Intent newIntent) {
- super.onNewIntent(newIntent);
- if (mFragment != null && ACTION_SAVE_COMPLETED.equals(newIntent.getAction())) {
- final Uri groupUri = newIntent.getData();
- Toast.makeText(this,
- groupUri == null ? R.string.groupSavedErrorToast :R.string.groupSavedToast,
- Toast.LENGTH_SHORT).show();
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(KEY_GROUP_METADATA, mGroupMetadata);
+ }
- if (groupUri != null) {
- final Intent intent = new Intent(this, GroupMembersActivity.class);
- intent.setData(groupUri);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ if (mIsInsertAction) {
+ mGroupMetadata = new GroupMetadata();
+ onGroupMetadataLoaded();
+ } else {
+ if (mGroupMetadata == null) {
+ getLoaderManager().restartLoader(
+ LOADER_GROUP_METADATA, null, mGroupMetadataCallbacks);
+ } else {
+ onGroupMetadataLoaded();
}
-
- finish();
}
}
- /** Whether the ActionBar is currently in selection mode. */
- public boolean isSelectionMode() {
- return mActionBarAdapter.isSelectionMode();
+ @Override
+ protected void onNewIntent(Intent newIntent) {
+ super.onNewIntent(newIntent);
+
+ if (ACTION_SAVE_COMPLETED.equals(newIntent.getAction())) {
+ final Uri groupUri = newIntent.getData();
+ if (groupUri == null) {
+ Toast.makeText(this, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
+ setResult(RESULT_CANCELED);
+ finish();
+ } else {
+ Toast.makeText(this, R.string.groupSavedToast,Toast.LENGTH_SHORT).show();
+
+ final Intent intent = GroupUtil.createViewGroupIntent(this, groupUri);
+ finish();
+ startActivity(intent);
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (mGroupMetadata == null || mGroupMetadata.memberCount < 0) {
+ // Hide menu options until metatdata is fully loaded
+ return false;
+ }
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.view_group, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ final boolean isSelectionMode = mActionBarAdapter.isSelectionMode();
+ final boolean isSearchMode = false;
+
+ final boolean isListFragment = mPagerAdapter.isCurrentItem(FRAGMENT_MEMBERS_LIST);
+ final boolean isEditorFragment = mPagerAdapter.isCurrentItem(FRAGMENT_EDITOR);
+
+ final boolean isGroupEditable = mGroupMetadata.editable;
+ final boolean isGroupReadOnly = mGroupMetadata.readOnly;
+
+ setVisible(menu, R.id.menu_edit_group, isGroupEditable && !isEditorFragment &&
+ !isSelectionMode && !isSearchMode);
+
+ setVisible(menu, R.id.menu_delete_group, !isGroupReadOnly && !isEditorFragment &&
+ !isSelectionMode && !isSearchMode);
+
+ setVisible(menu, R.id.menu_remove_from_group,
+ isGroupEditable && isSelectionMode && isListFragment);
+
+ return true;
+ }
+
+ private static void setVisible(Menu menu, int id, boolean visible) {
+ final MenuItem menuItem = menu.findItem(id);
+ if (menuItem != null) {
+ menuItem.setVisible(visible);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home: {
+ onBackPressed();
+ return true;
+ }
+ case R.id.menu_edit_group: {
+ mPagerAdapter.setCurrentItem(FRAGMENT_EDITOR);
+ return true;
+ }
+ case R.id.menu_delete_group: {
+ GroupDeletionDialogFragment.show(getFragmentManager(), mGroupMetadata.groupId,
+ mGroupMetadata.groupName, /* endActivity */ true);
+ return true;
+ }
+ case R.id.menu_remove_from_group: {
+ removeSelectedContacts();
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void removeSelectedContacts() {
+ final long[] rawContactsToRemove =
+ mMembersListFragment.getAdapter().getSelectedContactIdsArray();
+ final Intent intent = ContactSaveService.createGroupUpdateIntent(
+ this, mGroupMetadata.groupId, /* groupName */ null,
+ /* rawContactsToAdd */ null, rawContactsToRemove, getClass(),
+ GroupMembersActivity.ACTION_SAVE_COMPLETED);
+ startService(intent);
+ }
+
+ private void onGroupMetadataLoaded() {
+ if (DEBUG) Log.d(TAG, "Loaded " + mGroupMetadata);
+
+ if (mPagerAdapter == null) {
+ mPagerAdapter = new GroupPagerAdapter(getFragmentManager());
+ mViewPager.setAdapter(mPagerAdapter);
+ }
+
+ if (mIsInsertAction) {
+ mPagerAdapter.setCurrentItem(FRAGMENT_EDITOR);
+ getSupportActionBar().setTitle(getString(R.string.editGroupDescription));
+ } else {
+ getSupportActionBar().setTitle(mGroupMetadata.groupName);
+ mPagerAdapter.setCurrentItem(FRAGMENT_MEMBERS_LIST);
+ }
}
@Override
public void onBackPressed() {
- if (mActionBarAdapter.isSelectionMode()) {
+ if (mIsInsertAction) {
+ finish();
+ } else if (mActionBarAdapter.isSelectionMode()) {
mActionBarAdapter.setSelectionMode(false);
- mFragment.displayCheckBoxes(false);
+ if (mMembersListFragment != null) {
+ mMembersListFragment.displayCheckBoxes(false);
+ }
} else if (mActionBarAdapter.isSearchMode()) {
mActionBarAdapter.setSearchMode(false);
+ } else if (mPagerAdapter.isCurrentItem(FRAGMENT_EDITOR)) {
+ mPagerAdapter.setCurrentItem(FRAGMENT_MEMBERS_LIST);
} else {
super.onBackPressed();
}
}
- @Override
- public void onHomePressed() {
- onBackPressed();
- }
+ // GroupsMembersListFragment callbacks
@Override
- public void onGroupNameLoaded(String groupName) {
- getSupportActionBar().setTitle(groupName);
- }
-
- @Override
- public void onGroupMemberClicked(Uri contactLookupUri) {
+ public void onGroupMemberListItemClicked(Uri contactLookupUri) {
startActivity(ImplicitIntentsUtil.composeQuickContactIntent(
contactLookupUri, QuickContactActivity.MODE_FULLY_EXPANDED));
}
- @Override
- public void onEditGroup(Uri groupUri) {
- final Intent intent = new Intent(this, GroupEditorActivity.class);
- intent.setData(groupUri);
- intent.setAction(Intent.ACTION_EDIT);
- startActivity(intent);
- }
+ // ActionBarAdapter callbacks
@Override
public void onAction(int action) {
@@ -148,12 +438,16 @@
showFabWithAnimation(/* showFabWithAnimation = */ false);
break;
case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
- mFragment.displayCheckBoxes(true);
+ if (mMembersListFragment != null) {
+ mMembersListFragment.displayCheckBoxes(true);
+ }
invalidateOptionsMenu();
break;
case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
mActionBarAdapter.setSearchMode(false);
- mFragment.displayCheckBoxes(false);
+ if (mMembersListFragment != null) {
+ mMembersListFragment.displayCheckBoxes(false);
+ }
invalidateOptionsMenu();
showFabWithAnimation(/* showFabWithAnimation */ true);
break;
@@ -176,6 +470,8 @@
onBackPressed();
}
+ // MultiSelect checkbox callbacks
+
@Override
public void onStartDisplayingCheckBoxes() {
mActionBarAdapter.setSelectionMode(true);
@@ -184,7 +480,10 @@
@Override
public void onSelectedContactIdsChanged() {
- mActionBarAdapter.setSelectionCount(mFragment.getSelectedContactIds().size());
+ if (mActionBarAdapter.isSelectionMode() && mMembersListFragment != null) {
+ mActionBarAdapter.setSelectionCount(
+ mMembersListFragment.getSelectedContactIds().size());
+ }
invalidateOptionsMenu();
}
@@ -193,4 +492,40 @@
mActionBarAdapter.setSelectionMode(false);
invalidateOptionsMenu();
}
+
+ // GroupEditorFragment.Listener callbacks
+
+ @Override
+ public void onGroupNotFound() {
+ finish();
+ }
+
+ @Override
+ public void onReverted() {
+ if (mIsInsertAction) {
+ finish();
+ } else {
+ mPagerAdapter.setCurrentItem(FRAGMENT_MEMBERS_LIST);
+ }
+ }
+
+ @Override
+ public void onSaveFinished(int resultCode, Intent resultIntent) {
+ if (mIsInsertAction) {
+ final Intent intent = GroupUtil.createViewGroupIntent(this, resultIntent.getData());
+ finish();
+ startActivity(intent);
+ }
+ }
+
+ @Override
+ public void onAccountsNotFound() {
+ finish();
+ }
+
+ @Override
+ public void onGroupMemberClicked(Uri contactLookupUri) {
+ startActivity(ImplicitIntentsUtil.composeQuickContactIntent(
+ contactLookupUri, QuickContactActivity.MODE_FULLY_EXPANDED));
+ }
}
diff --git a/src/com/android/contacts/group/GroupEditorFragment.java b/src/com/android/contacts/group/GroupEditorFragment.java
index 25a07f1..c738e33 100644
--- a/src/com/android/contacts/group/GroupEditorFragment.java
+++ b/src/com/android/contacts/group/GroupEditorFragment.java
@@ -25,7 +25,6 @@
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentResolver;
-import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.content.DialogInterface;
@@ -59,9 +58,8 @@
import com.android.contacts.ContactSaveService;
import com.android.contacts.GroupMemberLoader;
import com.android.contacts.GroupMemberLoader.GroupEditorQuery;
-import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
-import com.android.contacts.activities.GroupEditorActivity;
+import com.android.contacts.activities.GroupMembersActivity;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.common.model.account.AccountType;
@@ -79,11 +77,13 @@
public class GroupEditorFragment extends Fragment implements SelectAccountDialogFragment.Listener {
private static final String TAG = "GroupEditorFragment";
- private static final String LEGACY_CONTACTS_AUTHORITY = "contacts";
+ private static final String ARG_ACTION = "action";
+ private static final String ARG_GROUP_METADATA = "groupMetadata";
+ private static final String ARG_INTENT_EXTRAS = "intentExtras";
private static final String KEY_ACTION = "action";
- private static final String KEY_GROUP_URI = "groupUri";
- private static final String KEY_GROUP_ID = "groupId";
+ private static final String KEY_GROUP_METADATA = "groupMetadata";
+ private static final String KEY_INTENT_EXTRAS = "intentExtras";
private static final String KEY_STATUS = "status";
private static final String KEY_ACCOUNT_NAME = "accountName";
private static final String KEY_ACCOUNT_TYPE = "accountType";
@@ -96,11 +96,11 @@
private static final String CURRENT_EDITOR_TAG = "currentEditorForAccount";
- public static interface Listener {
+ public interface Listener {
/**
* Group metadata was not found, close the fragment now.
*/
- public void onGroupNotFound();
+ void onGroupNotFound();
/**
* User has tapped Revert, close the fragment now.
@@ -123,7 +123,6 @@
void onGroupMemberClicked(Uri contactLookupUri);
}
- private static final int LOADER_GROUP_METADATA = 1;
private static final int LOADER_EXISTING_MEMBERS = 2;
private static final int LOADER_NEW_GROUP_MEMBER = 3;
@@ -165,7 +164,6 @@
*/
public enum Status {
SELECTING_ACCOUNT, // Account select dialog is showing
- LOADING, // Loader is fetching the group metadata
EDITING, // Not currently busy. We are waiting forthe user to enter data.
SAVING, // Data is currently being saved
CLOSING // Prevents any more saves
@@ -174,8 +172,8 @@
private Context mContext;
private String mAction;
private Bundle mIntentExtras;
- private Uri mGroupUri;
- private long mGroupId;
+ private GroupMetadata mGroupMetadata;
+
private Listener mListener;
private Status mStatus;
@@ -205,41 +203,72 @@
private ArrayList<Member> mListMembersToRemove = new ArrayList<Member>();
private ArrayList<Member> mListToDisplay = new ArrayList<Member>();
- public GroupEditorFragment() {
+ public static GroupEditorFragment newInstance(String action, GroupMetadata groupMetadata,
+ Bundle intentExtras) {
+ final Bundle args = new Bundle();
+ args.putString(ARG_ACTION, action);
+ args.putParcelable(ARG_GROUP_METADATA, groupMetadata);
+ args.putParcelable(ARG_INTENT_EXTRAS, intentExtras);
+ final GroupEditorFragment fragment = new GroupEditorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
setHasOptionsMenu(true);
+
mLayoutInflater = inflater;
mRootView = (ViewGroup) inflater.inflate(R.layout.group_editor_fragment, container, false);
return mRootView;
}
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mContext = activity;
- mPhotoManager = ContactPhotoManager.getInstance(mContext);
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (savedInstanceState == null) {
+ final Bundle args = getArguments();
+ if (args == null) {
+ throw new IllegalStateException("Group editor fragment created without arguments");
+ }
+ mAction = args.getString(ARG_ACTION);
+ mGroupMetadata = args.getParcelable(ARG_GROUP_METADATA);
+ mIntentExtras = args.getParcelable(ARG_INTENT_EXTRAS);
+ } else {
+ onRestoreInstanceState(savedInstanceState);
+ }
+
mMemberListAdapter = new MemberListAdapter();
}
@Override
+ public void onAttach(Activity context) {
+ super.onAttach(context);
+ mContext = context;
+ mPhotoManager = ContactPhotoManager.getInstance(mContext);
+ mContentResolver = mContext.getContentResolver();
+
+ try {
+ mListener = (Listener) getActivity();
+ } catch (ClassCastException e) {
+ throw new ClassCastException(getActivity() + " must implement " +
+ Listener.class.getSimpleName());
+ }
+ }
+
+ @Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
- // Just restore from the saved state. No loading.
- onRestoreInstanceState(savedInstanceState);
- if (mStatus == Status.SELECTING_ACCOUNT) {
- // Account select dialog is showing. Don't setup the editor yet.
- } else if (mStatus == Status.LOADING) {
- startGroupMetaDataLoader();
- } else {
+ if (mStatus != Status.SELECTING_ACCOUNT) {
setupEditorForAccount();
- }
+ } // else Account select dialog is showing. Don't setup the editor yet.
} else if (Intent.ACTION_EDIT.equals(mAction)) {
- startGroupMetaDataLoader();
+ bindGroupMetaData();
+ // Load existing members
+ getLoaderManager().initLoader(
+ LOADER_EXISTING_MEMBERS, null, mGroupMemberListLoaderListener);
} else if (Intent.ACTION_INSERT.equals(mAction)) {
final Account account = mIntentExtras == null ? null :
(Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
@@ -256,24 +285,15 @@
// No Account specified. Let the user choose from a disambiguation dialog.
selectAccountAndCreateGroup();
}
- } else {
- throw new IllegalArgumentException("Unknown Action String " + mAction +
- ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
}
}
- private void startGroupMetaDataLoader() {
- mStatus = Status.LOADING;
- getLoaderManager().initLoader(LOADER_GROUP_METADATA, null,
- mGroupMetaDataLoaderListener);
- }
-
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_ACTION, mAction);
- outState.putParcelable(KEY_GROUP_URI, mGroupUri);
- outState.putLong(KEY_GROUP_ID, mGroupId);
+ outState.putParcelable(KEY_GROUP_METADATA, mGroupMetadata);
+ outState.putParcelable(KEY_INTENT_EXTRAS, mIntentExtras);
outState.putSerializable(KEY_STATUS, mStatus);
outState.putString(KEY_ACCOUNT_NAME, mAccountName);
@@ -290,8 +310,8 @@
private void onRestoreInstanceState(Bundle state) {
mAction = state.getString(KEY_ACTION);
- mGroupUri = state.getParcelable(KEY_GROUP_URI);
- mGroupId = state.getLong(KEY_GROUP_ID);
+ mGroupMetadata = state.getParcelable(KEY_GROUP_METADATA);
+ mIntentExtras = state.getParcelable(KEY_INTENT_EXTRAS);
mStatus = (Status) state.getSerializable(KEY_STATUS);
mAccountName = state.getString(KEY_ACCOUNT_NAME);
@@ -306,13 +326,6 @@
mListToDisplay = state.getParcelableArrayList(KEY_MEMBERS_TO_DISPLAY);
}
- public void setContentResolver(ContentResolver resolver) {
- mContentResolver = resolver;
- if (mAutoCompleteAdapter != null) {
- mAutoCompleteAdapter.setContentResolver(mContentResolver);
- }
- }
-
private void selectAccountAndCreateGroup() {
final List<AccountWithDataSet> accounts =
AccountTypeManager.getInstance(mContext).getAccounts(true /* writeable */);
@@ -400,7 +413,10 @@
} else {
editorView = mRootView.findViewWithTag(CURRENT_EDITOR_TAG);
if (editorView == null) {
- throw new IllegalStateException("Group editor view not found");
+ // TODO(wjang): should not happen once this is fully integrated into group members
+ // activity so just let it go for now
+ // throw new IllegalStateException("Group editor view not found");
+ return;
}
}
@@ -466,26 +482,12 @@
mStatus = Status.EDITING;
}
- public void load(String action, Uri groupUri, Bundle intentExtras) {
- mAction = action;
- mGroupUri = groupUri;
- mGroupId = (groupUri != null) ? ContentUris.parseId(mGroupUri) : 0;
- mIntentExtras = intentExtras;
- }
-
- private void bindGroupMetaData(Cursor cursor) {
- if (!cursor.moveToFirst()) {
- Log.i(TAG, "Group not found with URI: " + mGroupUri + " Closing activity now.");
- if (mListener != null) {
- mListener.onGroupNotFound();
- }
- return;
- }
- mOriginalGroupName = cursor.getString(GroupMetaDataLoader.TITLE);
- mAccountName = cursor.getString(GroupMetaDataLoader.ACCOUNT_NAME);
- mAccountType = cursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
- mDataSet = cursor.getString(GroupMetaDataLoader.DATA_SET);
- mGroupNameIsReadOnly = (cursor.getInt(GroupMetaDataLoader.IS_READ_ONLY) == 1);
+ private void bindGroupMetaData() {
+ mOriginalGroupName = mGroupMetadata.groupName;
+ mAccountName = mGroupMetadata.accountName;
+ mAccountType = mGroupMetadata.accountType;
+ mDataSet = mGroupMetadata.dataSet;
+ mGroupNameIsReadOnly = mGroupMetadata.readOnly;
setupEditorForAccount();
// Setup the group metadata display
@@ -521,7 +523,11 @@
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: {
- getActivity().onBackPressed();
+ if (!hasNameChange() && !hasMembershipChange()) {
+ getActivity().onBackPressed();
+ } else {
+ CancelEditDialogFragment.show(this);
+ }
return true;
}
case R.id.menu_save:
@@ -586,7 +592,7 @@
// If there are no changes, then go straight to onSaveCompleted()
if (!hasNameChange() && !hasMembershipChange()) {
- onSaveCompleted(false, mGroupUri);
+ onSaveCompleted(false, mGroupMetadata.uri);
return true;
}
@@ -607,7 +613,7 @@
new AccountWithDataSet(mAccountName, mAccountType, mDataSet),
mGroupNameView.getText().toString(),
membersToAddArray, activity.getClass(),
- GroupEditorActivity.ACTION_SAVE_COMPLETED);
+ GroupMembersActivity.ACTION_SAVE_COMPLETED);
} else if (Intent.ACTION_EDIT.equals(mAction)) {
// Create array of raw contact IDs for contacts to add to the group
long[] membersToAddArray = convertToArray(mListMembersToAdd);
@@ -616,9 +622,10 @@
long[] membersToRemoveArray = convertToArray(mListMembersToRemove);
// Create the update intent (which includes the updated group name if necessary)
- saveIntent = ContactSaveService.createGroupUpdateIntent(activity, mGroupId,
+ saveIntent = ContactSaveService.createGroupUpdateIntent(activity,
+ mGroupMetadata.groupId,
getUpdatedName(), membersToAddArray, membersToRemoveArray,
- activity.getClass(), GroupEditorActivity.ACTION_SAVE_COMPLETED);
+ activity.getClass(), GroupMembersActivity.ACTION_SAVE_COMPLETED);
} else {
throw new IllegalStateException("Invalid intent action type " + mAction);
}
@@ -636,21 +643,8 @@
final Intent resultIntent;
final int resultCode;
if (success && groupUri != null) {
- final String requestAuthority = groupUri.getAuthority();
-
resultIntent = new Intent();
- if (LEGACY_CONTACTS_AUTHORITY.equals(requestAuthority)) {
- // Build legacy Uri when requested by caller
- final long groupId = ContentUris.parseId(groupUri);
- final Uri legacyContentUri = Uri.parse("content://contacts/groups");
- final Uri legacyUri = ContentUris.withAppendedId(
- legacyContentUri, groupId);
- resultIntent.setData(legacyUri);
- } else {
- // Otherwise pass back the given Uri
- resultIntent.setData(groupUri);
- }
-
+ resultIntent.setData(GroupUtil.maybeConvertToLegacyUri(groupUri));
resultCode = Activity.RESULT_OK;
} else {
resultCode = Activity.RESULT_CANCELED;
@@ -744,30 +738,6 @@
}
/**
- * The listener for the group metadata (i.e. group name, account type, and account name) loader.
- */
- private final LoaderManager.LoaderCallbacks<Cursor> mGroupMetaDataLoaderListener =
- new LoaderCallbacks<Cursor>() {
-
- @Override
- public CursorLoader onCreateLoader(int id, Bundle args) {
- return new GroupMetaDataLoader(mContext, mGroupUri);
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- bindGroupMetaData(data);
-
- // Load existing members
- getLoaderManager().initLoader(LOADER_EXISTING_MEMBERS, null,
- mGroupMemberListLoaderListener);
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {}
- };
-
- /**
* The loader listener for the list of existing group members.
*/
private final LoaderManager.LoaderCallbacks<Cursor> mGroupMemberListLoaderListener =
@@ -775,7 +745,8 @@
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
- return GroupMemberLoader.constructLoaderForGroupEditorQuery(mContext, mGroupId);
+ return GroupMemberLoader.constructLoaderForGroupEditorQuery(
+ mContext, mGroupMetadata.groupId);
}
@Override
diff --git a/src/com/android/contacts/group/GroupMembersListFragment.java b/src/com/android/contacts/group/GroupMembersListFragment.java
index fa3de1b..b896a4e 100644
--- a/src/com/android/contacts/group/GroupMembersListFragment.java
+++ b/src/com/android/contacts/group/GroupMembersListFragment.java
@@ -15,210 +15,44 @@
*/
package com.android.contacts.group;
-import android.app.Activity;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.CursorLoader;
-import android.content.Intent;
-import android.content.Loader;
-import android.database.Cursor;
+import android.content.Context;
import android.net.Uri;
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;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupListLoader;
-import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
-import com.android.contacts.activities.GroupMembersActivity;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.interactions.GroupDeletionDialogFragment;
import com.android.contacts.list.MultiSelectContactsListFragment;
/** Displays the members of a group. */
public class GroupMembersListFragment extends MultiSelectContactsListFragment {
- private static final String TAG = "GroupMembersList";
-
- private static final String KEY_GROUP_URI = "groupUri";
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;
-
- private final LoaderCallbacks<Cursor> mGroupMetadataCallbacks = new LoaderCallbacks<Cursor>() {
-
- @Override
- public CursorLoader onCreateLoader(int id, Bundle args) {
- return new GroupMetaDataLoader(getContext(), mGroupUri);
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
- if (cursor == null || cursor.isClosed()) {
- Log.e(TAG, "Failed to load group metadata");
- return;
- }
- if (cursor.moveToNext()) {
- final boolean deleted = cursor.getInt(GroupMetaDataLoader.DELETED) == 1;
- if (!deleted) {
- mGroupMetadata = new GroupMetadata();
- mGroupMetadata.accountType = cursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
- mGroupMetadata.dataSet = cursor.getString(GroupMetaDataLoader.DATA_SET);
- mGroupMetadata.groupId = cursor.getLong(GroupMetaDataLoader.GROUP_ID);
- mGroupMetadata.groupName = cursor.getString(GroupMetaDataLoader.TITLE);
- mGroupMetadata.readOnly = cursor.getInt(GroupMetaDataLoader.IS_READ_ONLY) == 1;
-
- final AccountTypeManager accountTypeManager =
- AccountTypeManager.getInstance(getContext());
- final AccountType accountType = accountTypeManager.getAccountType(
- mGroupMetadata.accountType, mGroupMetadata.dataSet);
- mGroupMetadata.editable = accountType.isGroupMembershipEditable();
-
- getLoaderManager().restartLoader(LOADER_GROUP_LIST_DETAILS, null,
- mGroupListDetailsCallbacks);
- }
- }
- }
-
- @Override
- 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>() {
-
- public GroupMetadata createFromParcel(Parcel in) {
- return new GroupMetadata(in);
- }
-
- public GroupMetadata[] newArray(int size) {
- return new GroupMetadata[size];
- }
- };
-
- String accountType;
- String dataSet;
- long groupId;
- String groupName;
- boolean readOnly;
- boolean editable;
- int memberCount = -1;
-
- GroupMetadata() {
- }
-
- GroupMetadata(Parcel source) {
- readFromParcel(source);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(accountType);
- dest.writeString(dataSet);
- dest.writeLong(groupId);
- dest.writeString(groupName);
- dest.writeInt(readOnly ? 1 : 0);
- dest.writeInt(editable ? 1 : 0);
- dest.writeInt(memberCount);
- }
-
- private void readFromParcel(Parcel source) {
- accountType = source.readString();
- dataSet = source.readString();
- groupId = source.readLong();
- groupName = source.readString();
- readOnly = source.readInt() == 1;
- editable = source.readInt() == 1;
- memberCount = source.readInt();
- }
-
- @Override
- public String toString() {
- return "GroupMetadata[accountType=" + accountType +
- " dataSet=" + dataSet +
- " groupId=" + groupId +
- " groupName=" + groupName +
- " readOnly=" + readOnly +
- " editable=" + editable +
- " memberCount=" + memberCount +
- "]";
- }
- }
+ private static final String ARG_GROUP_METADATA = "groupMetadata";
/** Callbacks for hosts of {@link GroupMembersListFragment}. */
- public interface GroupMembersListCallbacks {
-
- /** Invoked when the user hits back in the action bar. */
- void onHomePressed();
-
- /** Invoked after group metadata has been loaded. */
- void onGroupNameLoaded(String groupName);
+ public interface GroupMembersListListener {
/** Invoked when a group member in the list is clicked. */
- void onGroupMemberClicked(Uri contactLookupUri);
-
- /** Invoked when a user chooses ot edit the group whose members are being displayed. */
- void onEditGroup(Uri groupUri);
+ void onGroupMemberListItemClicked(Uri contactLookupUri);
}
- private Uri mGroupUri;
-
- private GroupMembersListCallbacks mCallbacks;
+ private GroupMembersListListener mListener;
private GroupMetadata mGroupMetadata;
+ public static GroupMembersListFragment newInstance(GroupMetadata groupMetadata) {
+ final Bundle args = new Bundle();
+ args.putParcelable(ARG_GROUP_METADATA, groupMetadata);
+
+ final GroupMembersListFragment fragment = new GroupMembersListFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
public GroupMembersListFragment() {
setHasOptionsMenu(true);
@@ -229,129 +63,53 @@
setQuickContactEnabled(false);
}
- /** Sets the Uri of the group whose members will be displayed. */
- public void setGroupUri(Uri groupUri) {
- mGroupUri = groupUri;
- }
-
- /** Sets a listener for group member click events. */
- public void setCallbacks(GroupMembersListCallbacks callbacks) {
- mCallbacks = callbacks;
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ try {
+ mListener = (GroupMembersListListener) getActivity();
+ } catch (ClassCastException e) {
+ throw new ClassCastException(getActivity() + " must implement " +
+ GroupMembersListListener.class.getSimpleName());
+ }
}
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
- if (savedState != null) {
- mGroupUri = savedState.getParcelable(KEY_GROUP_URI);
+ if (savedState == null) {
+ mGroupMetadata = getArguments().getParcelable(ARG_GROUP_METADATA);
+ } else {
mGroupMetadata = savedState.getParcelable(KEY_GROUP_METADATA);
}
+
+ // Don't attach the multi select check box listener if we can't edit the group
+ if (mGroupMetadata.editable) {
+ try {
+ setCheckBoxListListener((OnCheckBoxListActionListener) getActivity());
+ } catch (ClassCastException e) {
+ throw new ClassCastException(getActivity() + " must implement " +
+ OnCheckBoxListActionListener.class.getSimpleName());
+ }
+ }
+ }
+
+ @Override
+ public View onCreateView (LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View view = super.onCreateView(inflater, container, savedInstanceState);
+ bindMembersCount(view);
+ return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putParcelable(KEY_GROUP_URI, mGroupUri);
outState.putParcelable(KEY_GROUP_METADATA, mGroupMetadata);
}
- @Override
- protected void startLoading() {
- if (mGroupMetadata == null) {
- getLoaderManager().restartLoader(LOADER_GROUP_METADATA, null, mGroupMetadataCallbacks);
- } else {
- onGroupMetadataLoaded();
- }
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
- inflater.inflate(R.menu.view_group, menu);
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- final MenuItem editMenu = menu.findItem(R.id.menu_edit_group);
- editMenu.setVisible(!isSelectionMode() && isGroupEditable());
-
- final MenuItem deleteMenu = menu.findItem(R.id.menu_delete_group);
- deleteMenu.setVisible(!isSelectionMode() && isGroupDeletable());
-
- final MenuItem removeFromGroupMenu = menu.findItem(R.id.menu_remove_from_group);
- removeFromGroupMenu.setVisible(isSelectionMode());
- }
-
- private boolean isSelectionMode() {
- final GroupMembersActivity activity = (GroupMembersActivity) getActivity();
- return activity != null && activity.isSelectionMode();
- }
-
- private boolean isGroupEditable() {
- return mGroupUri != null && mGroupMetadata != null && mGroupMetadata.editable;
- }
-
- private boolean isGroupDeletable() {
- return mGroupUri != null && mGroupMetadata != null && !mGroupMetadata.readOnly;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home: {
- if (mCallbacks != null) {
- mCallbacks.onHomePressed();
- }
- return true;
- }
- case R.id.menu_edit_group: {
- if (mCallbacks != null) {
- mCallbacks.onEditGroup(mGroupUri);
- }
- break;
- }
- case R.id.menu_delete_group: {
- GroupDeletionDialogFragment.show(getFragmentManager(), mGroupMetadata.groupId,
- mGroupMetadata.groupName, /* endActivity */ true);
- return true;
- }
- case R.id.menu_remove_from_group: {
- removeSelectedContacts();
- return true;
- }
- }
- return false;
- }
-
- private void removeSelectedContacts() {
- final Activity activity = getActivity();
- if (activity != null) {
- final long[] rawContactsToRemove = getAdapter().getSelectedContactIdsArray();
- final Intent intent = ContactSaveService.createGroupUpdateIntent(
- activity, mGroupMetadata.groupId, /* groupName */ null,
- /* rawContactsToAdd */ null, rawContactsToRemove, activity.getClass(),
- GroupMembersActivity.ACTION_SAVE_COMPLETED);
- activity.startService(intent);
- }
- }
-
- private void onGroupMetadataLoaded() {
- final Activity activity = getActivity();
- if (activity != null) activity.invalidateOptionsMenu();
-
- // Set the title
- if (mCallbacks != null) {
- mCallbacks.onGroupNameLoaded(mGroupMetadata.groupName);
- }
-
- // Set the header
- bindMembersCount();
-
- // Start loading the group members
- super.startLoading();
- }
-
- private void bindMembersCount() {
- final View accountFilterContainer = getView().findViewById(
+ private void bindMembersCount(View view) {
+ final View accountFilterContainer = view.findViewById(
R.id.account_filter_header_container);
if (mGroupMetadata.memberCount >= 0) {
accountFilterContainer.setVisibility(View.VISIBLE);
@@ -382,9 +140,7 @@
@Override
protected void configureAdapter() {
super.configureAdapter();
- if (mGroupMetadata != null) {
- getAdapter().setGroupId(mGroupMetadata.groupId);
- }
+ getAdapter().setGroupId(mGroupMetadata.groupId);
}
@Override
@@ -402,9 +158,9 @@
super.onItemClick(position, id);
return;
}
- if (mCallbacks != null) {
+ if (mListener != null) {
final Uri contactLookupUri = getAdapter().getContactLookupUri(position);
- mCallbacks.onGroupMemberClicked(contactLookupUri);
+ mListener.onGroupMemberListItemClicked(contactLookupUri);
}
}
}
diff --git a/src/com/android/contacts/group/GroupMetadata.java b/src/com/android/contacts/group/GroupMetadata.java
new file mode 100644
index 0000000..788c1d4
--- /dev/null
+++ b/src/com/android/contacts/group/GroupMetadata.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 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.group;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** Meta data for a contact group. */
+// TODO(wjang): consolidate with com.android.contacts.common.GroupMetaData;
+public final class GroupMetadata implements Parcelable {
+
+ public static final Creator<GroupMetadata> CREATOR = new Creator<GroupMetadata>() {
+
+ public GroupMetadata createFromParcel(Parcel in) {
+ return new GroupMetadata(in);
+ }
+
+ public GroupMetadata[] newArray(int size) {
+ return new GroupMetadata[size];
+ }
+ };
+
+ // TODO(wjang): make them all final and add getters
+ public Uri uri;
+ public String accountName;
+ public String accountType;
+ public String dataSet;
+ public long groupId;
+ public String groupName;
+ public boolean readOnly;
+ public boolean editable;
+ public int memberCount = -1;
+
+ public GroupMetadata() {
+ }
+
+ public GroupMetadata(Parcel source) {
+ readFromParcel(source);
+ }
+
+ private void readFromParcel(Parcel source) {
+ uri = source.readParcelable(Uri.class.getClassLoader());
+ accountName = source.readString();
+ accountType = source.readString();
+ dataSet = source.readString();
+ groupId = source.readLong();
+ groupName = source.readString();
+ readOnly = source.readInt() == 1;
+ editable = source.readInt() == 1;
+ memberCount = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(uri, 0);
+ dest.writeString(accountName);
+ dest.writeString(accountType);
+ dest.writeString(dataSet);
+ dest.writeLong(groupId);
+ dest.writeString(groupName);
+ dest.writeInt(readOnly ? 1 : 0);
+ dest.writeInt(editable ? 1 : 0);
+ dest.writeInt(memberCount);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "GroupMetadata[uri=" + uri +
+ " accountName=" + accountName +
+ " accountType=" + accountType +
+ " dataSet=" + dataSet +
+ " groupId=" + groupId +
+ " groupName=" + groupName +
+ " readOnly=" + readOnly +
+ " editable=" + editable +
+ " memberCount=" + memberCount +
+ "]";
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/group/GroupUtil.java b/src/com/android/contacts/group/GroupUtil.java
index 6d6fec1..f9f5007 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.GroupEditorActivity;
import com.android.contacts.activities.GroupMembersActivity;
import com.google.common.base.Objects;
@@ -33,6 +32,9 @@
*/
public final class GroupUtil {
+ private static final String LEGACY_CONTACTS_AUTHORITY = "contacts";
+ private static final String LEGACY_CONTACTS_URI = "content://contacts/groups";
+
private GroupUtil() {
}
@@ -71,18 +73,40 @@
/** Returns an Intent to create a new group. */
public static Intent createAddGroupIntent(Context context) {
- final Intent intent = new Intent(context, GroupEditorActivity.class);
+ final Intent intent = new Intent(context, GroupMembersActivity.class);
intent.setAction(Intent.ACTION_INSERT);
return intent;
}
- /** Returns an Intent to view the details of the group identified by the given Uri. */
+ /** Returns an Intent to view the details of the group identified by the given ID. */
public static Intent createViewGroupIntent(Context context, long groupId) {
+ return createViewGroupIntent(context, getGroupUriFromId(groupId));
+ }
+
+ /** Returns an Intent to view the details of the group identified by the given Uri. */
+ public static Intent createViewGroupIntent(Context context, Uri uri) {
final Intent intent = new Intent(context, GroupMembersActivity.class);
- intent.setData(getGroupUriFromId(groupId));
+ intent.setAction(Intent.ACTION_VIEW);
+ // TODO(wjang): do we still need it?
+ // intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.setData(uri);
return intent;
}
+ /**
+ * Converts the given group Uri to the legacy format if the legacy authority was specified
+ * in the given Uri.
+ */
+ public static Uri maybeConvertToLegacyUri(Uri groupUri) {
+ final String requestAuthority = groupUri.getAuthority();
+ if (!LEGACY_CONTACTS_AUTHORITY.equals(requestAuthority)) {
+ return groupUri;
+ }
+ final long groupId = ContentUris.parseId(groupUri);
+ final Uri legacyContentUri = Uri.parse(LEGACY_CONTACTS_URI);
+ return ContentUris.withAppendedId(legacyContentUri, groupId);
+ }
+
/** TODO: Make it private after {@link GroupBrowseListAdapter} is removed. */
static Uri getGroupUriFromId(long groupId) {
return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
diff --git a/src/com/android/contacts/widget/NoSwipeViewPager.java b/src/com/android/contacts/widget/NoSwipeViewPager.java
new file mode 100644
index 0000000..b24df39
--- /dev/null
+++ b/src/com/android/contacts/widget/NoSwipeViewPager.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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.widget;
+
+import android.content.Context;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+/**
+ * ViewPager with swipe disabled.
+ */
+public class NoSwipeViewPager extends ViewPager {
+
+ public NoSwipeViewPager(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ return false;
+ }
+}
\ No newline at end of file