Let DefaultContactBrowseListFragment control actionbar, menu and more.
Test: manual or use GoogleContactsTests.apk
Bug: 30944495
Change-Id: Ic31df5cfe946363ff78254b7c82b042c13b107f4
diff --git a/src/com/android/contacts/ContactsDrawerActivity.java b/src/com/android/contacts/ContactsDrawerActivity.java
index 54bc4ad..1cfab16 100644
--- a/src/com/android/contacts/ContactsDrawerActivity.java
+++ b/src/com/android/contacts/ContactsDrawerActivity.java
@@ -281,6 +281,7 @@
@Override
protected void onNewIntent(Intent newIntent) {
+ mContactListFilterController.checkFilterValidity(false);
if (ACTION_CREATE_GROUP.equals(newIntent.getAction())) {
final Uri groupUri = newIntent.getData();
if (groupUri == null) {
@@ -522,7 +523,7 @@
}
}
- protected void updateFilterMenu(ContactListFilter filter) {
+ public void updateFilterMenu(ContactListFilter filter) {
clearCheckedMenus();
if (filter != null && filter.isContactsFilterType()) {
if (mIdMenuMap != null && mIdMenuMap.get(R.id.nav_all_contacts) != null) {
@@ -591,7 +592,7 @@
protected void switchToAllContacts() {
final Intent intent = new Intent();
- final ContactListFilter filter = createContactsFilter();
+ final ContactListFilter filter = AccountFilterUtil.createContactsFilter(this);
intent.putExtra(AccountFilterActivity.EXTRA_CONTACT_LIST_FILTER, filter);
AccountFilterUtil.handleAccountFilterResult(
mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
@@ -605,19 +606,6 @@
Assistants.getDuplicatesActivityIntent(this));
}
- /**
- * Returns a {@link ContactListFilter} of type
- * {@link ContactListFilter#FILTER_TYPE_ALL_ACCOUNTS}, or if a custom "Contacts to display"
- * filter has been set, then one of type {@link ContactListFilter#FILTER_TYPE_CUSTOM}.
- */
- protected ContactListFilter createContactsFilter() {
- final int filterType =
- ContactListFilterController.getInstance(this).isCustomFilterPersisted()
- ? ContactListFilter.FILTER_TYPE_CUSTOM
- : ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS;
- return ContactListFilter.createFilterWithType(filterType);
- }
-
private void clearCheckedMenus() {
clearCheckedMenu(mFilterMenuMap);
clearCheckedMenu(mGroupMenuMap);
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 8cef3e3..d596398 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -23,39 +23,30 @@
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.BroadcastReceiver;
-import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SyncStatusObserver;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.ProviderStatus;
-import android.provider.ContactsContract.QuickContact;
import android.support.design.widget.CoordinatorLayout;
-import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.SwipeRefreshLayout;
-import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.Menu;
-import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageButton;
import android.widget.Toast;
@@ -64,74 +55,46 @@
import com.android.contacts.R;
import com.android.contacts.common.Experiments;
import com.android.contacts.common.activity.RequestPermissionsActivity;
-import com.android.contacts.common.compat.CompatUtils;
import com.android.contacts.common.interactions.ImportExportDialogFragment;
-import com.android.contacts.common.list.ContactEntryListFragment;
import com.android.contacts.common.list.ContactListFilter;
-import com.android.contacts.common.list.ContactListFilterController;
import com.android.contacts.common.list.DirectoryListLoader;
import com.android.contacts.common.list.ProviderStatusWatcher;
import com.android.contacts.common.list.ProviderStatusWatcher.ProviderStatusListener;
-import com.android.contacts.common.logging.ListEvent;
import com.android.contacts.common.logging.Logger;
import com.android.contacts.common.logging.ScreenEvent.ScreenType;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.model.account.GoogleAccountType;
+import com.android.contacts.common.util.AccountFilterUtil;
import com.android.contacts.common.util.Constants;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.common.widget.FloatingActionButtonController;
import com.android.contacts.editor.EditorIntents;
-import com.android.contacts.interactions.ContactDeletionInteraction;
-import com.android.contacts.interactions.ContactMultiDeletionInteraction;
-import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
import com.android.contacts.list.ContactsIntentResolver;
import com.android.contacts.list.ContactsRequest;
import com.android.contacts.list.ContactsUnavailableFragment;
import com.android.contacts.list.DefaultContactBrowseListFragment;
-import com.android.contacts.list.MultiSelectContactsListFragment.OnCheckBoxListActionListener;
-import com.android.contacts.list.OnContactBrowserActionListener;
import com.android.contacts.list.OnContactsUnavailableActionListener;
import com.android.contacts.quickcontact.QuickContactActivity;
-import com.android.contacts.util.DialogManager;
-import com.android.contacts.util.SharedPreferenceUtil;
import com.android.contacts.util.SyncUtil;
import com.android.contactsbind.experiments.Flags;
import com.android.contacts.widget.FloatingActionButtonBehavior;
import com.google.android.libraries.material.featurehighlight.FeatureHighlight;
import java.util.List;
-import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Displays a list to browse contacts.
*/
-public class PeopleActivity extends ContactsDrawerActivity implements
- View.OnCreateContextMenuListener,
- View.OnClickListener,
- ActionBarAdapter.Listener,
- DialogManager.DialogShowingViewActivity,
- ContactListFilterController.ContactListFilterListener,
- ProviderStatusListener,
- MultiContactDeleteListener,
- DefaultContactBrowseListFragment.FeatureHighlightCallback {
+public class PeopleActivity extends ContactsDrawerActivity implements ProviderStatusListener {
private static final String TAG = "PeopleActivity";
- private static final String ENABLE_DEBUG_OPTIONS_HIDDEN_CODE = "debug debug!";
-
private static final String TAG_ALL = "contacts-all";
- private static final int ACTIVITY_REQUEST_CODE_SHARE = 0;
-
- private final DialogManager mDialogManager = new DialogManager(this);
-
private ContactsIntentResolver mIntentResolver;
private ContactsRequest mRequest;
- private ActionBarAdapter mActionBarAdapter;
- private List<AccountWithDataSet> mWritableAccounts;
private FloatingActionButtonController mFloatingActionButtonController;
private View mFloatingActionButtonContainer;
private boolean wasLastFabAnimationScaleIn = false;
@@ -142,8 +105,6 @@
private BroadcastReceiver mSaveServiceListener;
- private boolean mOptionsMenuContactsAvailable;
-
private CoordinatorLayout mLayoutRoot;
/**
@@ -153,8 +114,6 @@
private View mContactsView;
- private boolean mEnableDebugMenuOptions;
-
/**
* True if this activity instance is a re-created one. i.e. set true after orientation change.
* This is set in {@link #onCreate} for later use in {@link #onStart}.
@@ -169,10 +128,6 @@
*/
private boolean mFragmentInitialized;
- /**
- * This is to disable {@link #onOptionsItemSelected} when we trying to stop the activity.
- */
- private boolean mDisableOptionItemSelected;
/** Sequential ID assigned to each instance; used for logging */
private final int mInstanceId;
@@ -194,11 +149,12 @@
// Update sync status for accounts in current ContactListFilter
private void onSyncStateUpdated() {
- if (mActionBarAdapter.isSearchMode() || mActionBarAdapter.isSelectionMode()) {
+ if (mAllFragment.getActionBarAdapter().isSearchMode()
+ || mAllFragment.getActionBarAdapter().isSelectionMode()) {
return;
}
- final ContactListFilter filter = mContactListFilterController.getFilter();
+ final ContactListFilter filter = mAllFragment.getFilter();
if (filter != null) {
final SwipeRefreshLayout swipeRefreshLayout = mAllFragment.getSwipeRefreshLayout();
if (swipeRefreshLayout == null) {
@@ -277,22 +233,12 @@
finish();
return;
}
- mContactListFilterController = ContactListFilterController.getInstance(this);
- mContactListFilterController.checkFilterValidity(false);
- mContactListFilterController.addListener(this);
mProviderStatusWatcher.addListener(this);
mIsRecreatedInstance = (savedState != null);
- // Use FILTER_TYPE_ALL_ACCOUNTS filter if the activity is not a re-created one.
- // This is useful when user upgrades app while an account filter or a custom filter was
- // stored in sharedPreference in a previous version of Contacts app.
- final ContactListFilter filter = mIsRecreatedInstance
- ? mContactListFilterController.getFilter() : createContactsFilter();
- persistFilterIfNeeded(filter);
-
- createViewsAndFragments(savedState);
+ createViewsAndFragments();
if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity.onCreate finish");
@@ -300,18 +246,6 @@
getWindow().setBackgroundDrawable(null);
}
- private void maybeShowHamburgerFeatureHighlight() {
- if (!mActionBarAdapter.isSearchMode() && !mActionBarAdapter.isSelectionMode()
- && SharedPreferenceUtil.getShouldShowHamburgerPromo(this)) {
- final FeatureHighlight hamburgerFeatureHighlight =
- mActionBarAdapter.getHamburgerFeatureHighlight();
- if (hamburgerFeatureHighlight != null) {
- hamburgerFeatureHighlight.show(this);
- SharedPreferenceUtil.setHamburgerPromoDisplayedBefore(this);
- }
- }
- }
-
@Override
protected void onNewIntent(Intent intent) {
if (ContactsDrawerActivity.ACTION_CREATE_GROUP.equals(intent.getAction())) {
@@ -324,9 +258,12 @@
finish();
return;
}
- mActionBarAdapter.initialize(null, mRequest);
- mContactListFilterController.checkFilterValidity(false);
+ // Re-initialize ActionBarAdapter because {@link #onNewIntent(Intent)} doesn't invoke
+ // {@link Fragment#onActivityCreated(Bundle)} where we initialize ActionBarAdapter
+ // initially.
+ mAllFragment.setContactsRequest(mRequest);
+ mAllFragment.initializeActionBarAdapter(null);
// Re-configure fragments.
configureFragments(true /* from request */);
@@ -372,7 +309,7 @@
return true;
}
- private void createViewsAndFragments(Bundle savedState) {
+ private void createViewsAndFragments() {
setContentView(R.layout.people_activity);
final FragmentManager fragmentManager = getFragmentManager();
@@ -390,29 +327,25 @@
transaction.add(R.id.contacts_list_container, mAllFragment, TAG_ALL);
}
- mAllFragment.setFeatureHighlightCallback(this);
- mAllFragment.setOnContactListActionListener(new ContactBrowserActionListener());
- mAllFragment.setCheckBoxListListener(new CheckBoxListListener());
- mAllFragment.setListType(mContactListFilterController.getFilterListType());
-
- // Hide all fragments for now. We adjust visibility when we get
- // onAction(Action.STOP_SEARCH_AND_SELECTION_MODE) from ActionBarAdapter.
- transaction.hide(mAllFragment);
+ mAllFragment.setContactsAvailable(areContactsAvailable());
+ mAllFragment.setListType();
+ mAllFragment.setContactsRequest(mRequest);
transaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
- mActionBarAdapter = new ActionBarAdapter(this, this, getSupportActionBar(), mToolbar);
- mActionBarAdapter.initialize(savedState, mRequest);
-
// Configure floating action button
mFloatingActionButtonContainer = findViewById(R.id.floating_action_button_container);
final ImageButton floatingActionButton
= (ImageButton) findViewById(R.id.floating_action_button);
- floatingActionButton.setOnClickListener(this);
+ floatingActionButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onFabClicked();
+ }
+ });
mFloatingActionButtonController = new FloatingActionButtonController(this,
mFloatingActionButtonContainer, floatingActionButton);
- initializeFabVisibility();
invalidateOptionsMenuIfNeeded();
@@ -454,7 +387,6 @@
@Override
protected void onPause() {
- mOptionsMenuContactsAvailable = false;
mProviderStatusWatcher.stop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mSaveServiceListener);
@@ -474,12 +406,6 @@
mProviderStatusWatcher.start();
updateViewConfiguration(true);
- // Re-register the listener, which may have been cleared when onSaveInstanceState was
- // called. See also: onSaveInstanceState
- mActionBarAdapter.setListener(this);
- mDisableOptionItemSelected = false;
- updateFragmentsVisibility();
-
if (Flags.getInstance(this).getBoolean(Experiments.PULL_TO_REFRESH)) {
mStatusChangeListenerHandle = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE
@@ -488,7 +414,8 @@
mSyncStatusObserver);
onSyncStateUpdated();
}
- maybeShowHamburgerFeatureHighlight();
+ mAllFragment.maybeShowHamburgerFeatureHighlight();
+ initializeFabVisibility();
mSaveServiceListener = new SaveServiceListener();
LocalBroadcastManager.getInstance(this).registerReceiver(mSaveServiceListener,
@@ -498,16 +425,6 @@
@Override
protected void onDestroy() {
mProviderStatusWatcher.removeListener(this);
-
- // Some of variables will be null if this Activity redirects Intent.
- // See also onCreate() or other methods called during the Activity's initialization.
- if (mActionBarAdapter != null) {
- mActionBarAdapter.setListener(null);
- }
- if (mContactListFilterController != null) {
- mContactListFilterController.removeListener(this);
- }
-
super.onDestroy();
}
@@ -518,7 +435,7 @@
boolean searchMode = mRequest.isSearchMode();
switch (actionCode) {
case ContactsRequest.ACTION_ALL_CONTACTS:
- filter = createContactsFilter();
+ filter = AccountFilterUtil.createContactsFilter(this);
break;
case ContactsRequest.ACTION_CONTACTS_WITH_PHONES:
filter = ContactListFilter.createFilterWithType(
@@ -534,7 +451,7 @@
}
if (filter != null) {
- mContactListFilterController.setContactListFilter(filter, /* persistent */ false);
+ mAllFragment.setContactListFilter(filter);
searchMode = false;
}
@@ -542,39 +459,26 @@
searchMode = false;
}
- mActionBarAdapter.setSearchMode(searchMode);
+ mAllFragment.getActionBarAdapter().setSearchMode(searchMode);
configureContactListFragmentForRequest();
}
- configureContactListFragment();
-
- invalidateOptionsMenuIfNeeded();
+ mAllFragment.configureContactListFragment();
}
private void initializeFabVisibility() {
- final boolean hideFab = mActionBarAdapter.isSearchMode()
- || mActionBarAdapter.isSelectionMode()
- || !shouldShowFabForAccount();
- mFloatingActionButtonContainer.setVisibility(hideFab ? View.GONE : View.VISIBLE);
+ mFloatingActionButtonContainer.setVisibility(shouldHideFab() ? View.GONE : View.VISIBLE);
mFloatingActionButtonController.resetIn();
- wasLastFabAnimationScaleIn = !hideFab;
+ wasLastFabAnimationScaleIn = !shouldHideFab();
}
- private boolean shouldShowFabForAccount() {
- return isCurrentAccountFilterWritable()
- || isAllContactsFilter(mContactListFilterController.getFilter());
+ private boolean shouldHideFab() {
+ if (mAllFragment.getActionBarAdapter() == null) return false;
+ return mAllFragment.getActionBarAdapter().isSearchMode()
+ || mAllFragment.getActionBarAdapter().isSelectionMode();
}
- private boolean isCurrentAccountFilterWritable() {
- final ContactListFilter currentFilter = mContactListFilterController.getFilter();
- final AccountWithDataSet accountOfCurrentFilter = new AccountWithDataSet(
- currentFilter.accountName, currentFilter.accountType, currentFilter.dataSet);
- return accountOfCurrentFilter.isLocalAccount()
- || (mWritableAccounts != null
- && mWritableAccounts.contains(accountOfCurrentFilter));
- }
-
- private void showFabWithAnimation(boolean showFab) {
+ public void showFabWithAnimation(boolean showFab) {
if (mFloatingActionButtonContainer == null) {
return;
}
@@ -594,99 +498,6 @@
}
}
- @Override
- public void onContactListFilterChanged() {
- if (mAllFragment == null || !mAllFragment.isAdded()) {
- return;
- }
-
- setFilterAndUpdateTitle(mContactListFilterController.getFilter());
- // Scroll to top after filter is changed.
- mAllFragment.getListView().setSelection(0);
- showFabWithAnimation(shouldShowFabForAccount());
-
- invalidateOptionsMenuIfNeeded();
- }
-
- /**
- * Handler for action bar actions.
- */
- @Override
- public void onAction(int action) {
- switch (action) {
- case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
- mAllFragment.displayCheckBoxes(true);
- startSearchOrSelectionMode();
- break;
- case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
- if (!mIsRecreatedInstance) {
- Logger.logScreenView(this, ScreenType.SEARCH);
- }
- startSearchOrSelectionMode();
- break;
- case ActionBarAdapter.Listener.Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE:
- showFabWithAnimation(shouldShowFabForAccount());
- break;
- case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
- // If queryString is empty, fragment data will not be reloaded,
- // so hamburger promo should be checked now.
- // If not empty, promo should be checked and displayed after reloading. (b/30706521)
- if (TextUtils.isEmpty(mAllFragment.getQueryString())) {
- maybeShowHamburgerFeatureHighlight();
- }
- setQueryTextToFragment("");
- updateFragmentsVisibility();
- invalidateOptionsMenu();
- showFabWithAnimation(shouldShowFabForAccount());
- // Determine whether the account has pullToRefresh feature
- if (Flags.getInstance(this).getBoolean(Experiments.PULL_TO_REFRESH)) {
- setSwipeRefreshLayoutEnabledOrNot(mContactListFilterController.getFilter());
- }
- break;
- case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
- final String queryString = mActionBarAdapter.getQueryString();
- setQueryTextToFragment(queryString);
- updateDebugOptionsVisibility(
- ENABLE_DEBUG_OPTIONS_HIDDEN_CODE.equals(queryString));
- break;
- default:
- throw new IllegalStateException("Unkonwn ActionBarAdapter action: " + action);
- }
- }
-
- private void startSearchOrSelectionMode() {
- configureFragments(false /* from request */);
- updateFragmentsVisibility();
- invalidateOptionsMenu();
- showFabWithAnimation(/* showFab */ false);
- if (!SharedPreferenceUtil.getHamburgerPromoTriggerActionHappenedBefore(this)) {
- SharedPreferenceUtil.setHamburgerPromoTriggerActionHappenedBefore(this);
- }
- }
-
- @Override
- public void onUpButtonPressed() {
- onBackPressed();
- }
-
- private void updateDebugOptionsVisibility(boolean visible) {
- if (mEnableDebugMenuOptions != visible) {
- mEnableDebugMenuOptions = visible;
- invalidateOptionsMenu();
- }
- }
-
- /**
- * Updates the fragment/view visibility according to the current mode, such as
- * {@link ActionBarAdapter#isSearchMode()}.
- */
- private void updateFragmentsVisibility() {
- if (!mActionBarAdapter.isSelectionMode()) {
- mAllFragment.displayCheckBoxes(false);
- }
- invalidateOptionsMenu();
- }
-
private void setQueryTextToFragment(String query) {
mAllFragment.setQueryString(query, true);
mAllFragment.setVisibleScrollbarEnabled(!mAllFragment.isSearchMode());
@@ -698,8 +509,7 @@
mAllFragment.setSelectedContactUri(contactUri);
}
- setFilterAndUpdateTitle(mContactListFilterController.getFilter());
- setQueryTextToFragment(mActionBarAdapter.getQueryString());
+ setQueryTextToFragment(mAllFragment.getActionBarAdapter().getQueryString());
if (mRequest.isDirectorySearchEnabled()) {
mAllFragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_DEFAULT);
@@ -708,28 +518,9 @@
}
}
- private void configureContactListFragment() {
- // Filter may be changed when this Activity is in background.
- setFilterAndUpdateTitle(mContactListFilterController.getFilter());
-
- mAllFragment.setVerticalScrollbarPosition(getScrollBarPosition());
- mAllFragment.setSelectionVisible(false);
- }
-
- private int getScrollBarPosition() {
- return isRTL() ? View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
- }
-
- private boolean isRTL() {
- final Locale locale = Locale.getDefault();
- return TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
- }
-
@Override
public void onFiltersLoaded(List<ContactListFilter> accountFilterItems) {
super.onFiltersLoaded(accountFilterItems);
- mWritableAccounts =
- AccountTypeManager.getInstance(this).getAccounts(/* contactWritableOnly */ true);
initializeFabVisibility();
}
@@ -773,22 +564,28 @@
}
if (mAllFragment != null) {
+ getFragmentManager().beginTransaction()
+ .show(mAllFragment)
+ .commitAllowingStateLoss();
+ mAllFragment.setContactsAvailable(areContactsAvailable());
mAllFragment.setEnabled(true);
}
} else {
+ final FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Setting up the page so that the user can still use the app
// even without an account.
if (mAllFragment != null) {
mAllFragment.setEnabled(false);
+ transaction.hide(mAllFragment);
}
if (mContactsUnavailableFragment == null) {
mContactsUnavailableFragment = new ContactsUnavailableFragment();
mContactsUnavailableFragment.setOnContactsUnavailableActionListener(
new ContactsUnavailableFragmentListener());
- getFragmentManager().beginTransaction()
- .replace(R.id.contacts_unavailable_container, mContactsUnavailableFragment)
- .commitAllowingStateLoss();
+ transaction.replace(
+ R.id.contacts_unavailable_container, mContactsUnavailableFragment);
}
+ transaction.commitAllowingStateLoss();
mContactsUnavailableFragment.updateStatus(mProviderStatus);
// Show the contactsUnavailableView, and hide the mContactsView so that we don't
@@ -815,94 +612,6 @@
return !allAccounts.get(0).isLocalAccount();
}
- private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
- ContactBrowserActionListener() {}
-
- @Override
- public void onSelectionChange() {
-
- }
-
- @Override
- public void onViewContactAction(int position, Uri contactLookupUri,
- boolean isEnterpriseContact) {
- if (isEnterpriseContact) {
- // No implicit intent as user may have a different contacts app in work profile.
- QuickContact.showQuickContact(PeopleActivity.this, new Rect(), contactLookupUri,
- QuickContactActivity.MODE_FULLY_EXPANDED, null);
- } else {
- final Intent intent = ImplicitIntentsUtil.composeQuickContactIntent(
- PeopleActivity.this, contactLookupUri,
- QuickContactActivity.MODE_FULLY_EXPANDED);
- final int previousScreen;
- if (mAllFragment.isSearchMode()) {
- previousScreen = ScreenType.SEARCH;
- } else {
- if (isAllContactsFilter(mContactListFilterController.getFilter())) {
- if (position < mAllFragment.getAdapter().getNumberOfFavorites()) {
- previousScreen = ScreenType.FAVORITES;
- } else {
- previousScreen = ScreenType.ALL_CONTACTS;
- }
- } else {
- previousScreen = ScreenType.LIST_ACCOUNT;
- }
- }
- Logger.logListEvent(ListEvent.ActionType.CLICK,
- /* listType */ getListTypeIncludingSearch(),
- /* count */ mAllFragment.getAdapter().getCount(),
- /* clickedIndex */ position, /* numSelected */ 0);
- intent.putExtra(QuickContactActivity.EXTRA_PREVIOUS_SCREEN_TYPE, previousScreen);
- ImplicitIntentsUtil.startActivityInApp(PeopleActivity.this, intent);
- }
- }
-
- @Override
- public void onDeleteContactAction(Uri contactUri) {
- ContactDeletionInteraction.start(PeopleActivity.this, contactUri, false);
- }
-
- @Override
- public void onFinishAction() {
- onBackPressed();
- }
-
- @Override
- public void onInvalidSelection() {
- ContactListFilter filter;
- ContactListFilter currentFilter = mAllFragment.getFilter();
- if (currentFilter != null
- && currentFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
- filter = createContactsFilter();
- setFilterAndUpdateTitle(filter);
- } else {
- filter = ContactListFilter.createFilterWithType(
- ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
- setFilterAndUpdateTitle(filter, /* restoreSelectedUri */ false);
- }
- persistFilterIfNeeded(filter);
- }
- }
-
- private final class CheckBoxListListener implements OnCheckBoxListActionListener {
- @Override
- public void onStartDisplayingCheckBoxes() {
- mActionBarAdapter.setSelectionMode(true);
- invalidateOptionsMenu();
- }
-
- @Override
- public void onSelectedContactIdsChanged() {
- mActionBarAdapter.setSelectionCount(mAllFragment.getSelectedContactIds().size());
- invalidateOptionsMenu();
- }
-
- @Override
- public void onStopDisplayingCheckBoxes() {
- mActionBarAdapter.setSelectionMode(false);
- }
- }
-
private class ContactsUnavailableFragmentListener
implements OnContactsUnavailableActionListener {
ContactsUnavailableFragmentListener() {}
@@ -925,232 +634,19 @@
}
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- if (!areContactsAvailable()) {
- // If contacts aren't available, hide all menu items.
- return false;
- }
- super.onCreateOptionsMenu(menu);
-
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.people_options, menu);
-
- return true;
- }
-
private void invalidateOptionsMenuIfNeeded() {
- if (isOptionsMenuChanged()) {
+ if (mAllFragment != null
+ || mAllFragment.getOptionsMenuContactsAvailable() != areContactsAvailable()) {
invalidateOptionsMenu();
}
}
- public boolean isOptionsMenuChanged() {
- if (mOptionsMenuContactsAvailable != areContactsAvailable()) {
- return true;
- }
-
- if (mAllFragment != null && mAllFragment.isOptionsMenuChanged()) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- mOptionsMenuContactsAvailable = areContactsAvailable();
- if (!mOptionsMenuContactsAvailable) {
- return false;
- }
-
- final boolean isSearchOrSelectionMode = mActionBarAdapter.isSearchMode()
- || mActionBarAdapter.isSelectionMode();
- makeMenuItemVisible(menu, R.id.menu_search, !isSearchOrSelectionMode);
-
- final boolean showSelectedContactOptions = mActionBarAdapter.isSelectionMode()
- && mAllFragment.getSelectedContactIds().size() != 0;
- makeMenuItemVisible(menu, R.id.menu_share, showSelectedContactOptions);
- makeMenuItemVisible(menu, R.id.menu_delete, showSelectedContactOptions);
- final boolean showLinkContactsOptions = mActionBarAdapter.isSelectionMode()
- && mAllFragment.getSelectedContactIds().size() > 1;
- makeMenuItemVisible(menu, R.id.menu_join, showLinkContactsOptions);
-
- // Debug options need to be visible even in search mode.
- makeMenuItemVisible(menu, R.id.export_database, mEnableDebugMenuOptions &&
- hasExportIntentHandler());
-
- return true;
- }
-
- private boolean hasExportIntentHandler() {
- final Intent intent = new Intent();
- intent.setAction("com.android.providers.contacts.DUMP_DATABASE");
- final List<ResolveInfo> receivers = getPackageManager().queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
- return receivers != null && receivers.size() > 0;
- }
-
- private void makeMenuItemVisible(Menu menu, int itemId, boolean visible) {
- final MenuItem item = menu.findItem(itemId);
- if (item != null) {
- item.setVisible(visible);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (mDisableOptionItemSelected) {
- return false;
- }
-
- switch (item.getItemId()) {
- case android.R.id.home: {
- // The home icon on the action bar is pressed
- if (mActionBarAdapter.isUpShowing()) {
- // "UP" icon press -- should be treated as "back".
- onBackPressed();
- }
- return true;
- }
- case R.id.menu_search: {
- onSearchRequested();
- return true;
- }
- case R.id.menu_share: {
- shareSelectedContacts();
- return true;
- }
- case R.id.menu_join: {
- Logger.logListEvent(ListEvent.ActionType.LINK,
- /* listType */ getListTypeIncludingSearch(),
- /* count */ mAllFragment.getAdapter().getCount(), /* clickedIndex */ -1,
- /* numSelected */ mAllFragment.getAdapter().getSelectedContactIds().size());
- joinSelectedContacts();
- return true;
- }
- case R.id.menu_delete: {
- deleteSelectedContacts();
- return true;
- }
- case R.id.export_database: {
- final Intent intent = new Intent("com.android.providers.contacts.DUMP_DATABASE");
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
- ImplicitIntentsUtil.startActivityOutsideApp(this, intent);
- return true;
- }
- }
- return super.onOptionsItemSelected(item);
- }
-
private void showImportExportDialogFragment(){
ImportExportDialogFragment.show(getFragmentManager(), areContactsAvailable(),
PeopleActivity.class, ImportExportDialogFragment.EXPORT_MODE_ALL_CONTACTS);
}
@Override
- public boolean onSearchRequested() { // Search key pressed.
- if (!mActionBarAdapter.isSelectionMode()) {
- mActionBarAdapter.setSearchMode(true);
- }
- return true;
- }
-
- /**
- * Share all contacts that are currently selected in mAllFragment. This method is pretty
- * inefficient for handling large numbers of contacts. I don't expect this to be a problem.
- */
- private void shareSelectedContacts() {
- final StringBuilder uriListBuilder = new StringBuilder();
- for (Long contactId : mAllFragment.getSelectedContactIds()) {
- final Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
- final Uri lookupUri = Contacts.getLookupUri(getContentResolver(), contactUri);
- if (lookupUri == null) {
- continue;
- }
- final List<String> pathSegments = lookupUri.getPathSegments();
- if (pathSegments.size() < 2) {
- continue;
- }
- final String lookupKey = pathSegments.get(pathSegments.size() - 2);
- if (uriListBuilder.length() > 0) {
- uriListBuilder.append(':');
- }
- uriListBuilder.append(Uri.encode(lookupKey));
- }
- if (uriListBuilder.length() == 0) {
- return;
- }
- final Uri uri = Uri.withAppendedPath(
- Contacts.CONTENT_MULTI_VCARD_URI,
- Uri.encode(uriListBuilder.toString()));
- final Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType(Contacts.CONTENT_VCARD_TYPE);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
- try {
- startActivityForResult(Intent.createChooser(intent, getResources().getQuantityString(
- R.plurals.title_share_via,
- /* quantity */ mAllFragment.getSelectedContactIds().size()))
- , ACTIVITY_REQUEST_CODE_SHARE);
- } catch (final ActivityNotFoundException ex) {
- Toast.makeText(this, R.string.share_error, Toast.LENGTH_SHORT).show();
- }
- }
-
- private void joinSelectedContacts() {
- final Intent intent = ContactSaveService.createJoinSeveralContactsIntent(
- this, mAllFragment.getSelectedContactIdsArray());
- this.startService(intent);
-
- mActionBarAdapter.setSelectionMode(false);
- }
-
- private void deleteSelectedContacts() {
- ContactMultiDeletionInteraction.start(PeopleActivity.this,
- mAllFragment.getSelectedContactIds());
- }
-
- @Override
- public void onDeletionFinished() {
- // The parameters count and numSelected are both the number of contacts before deletion.
- Logger.logListEvent(ListEvent.ActionType.DELETE,
- /* listType */ getListTypeIncludingSearch(),
- /* count */ mAllFragment.getAdapter().getCount(), /* clickedIndex */ -1,
- /* numSelected */ mAllFragment.getSelectedContactIds().size());
- mActionBarAdapter.setSelectionMode(false);
- }
-
- private int getListTypeIncludingSearch() {
- return mAllFragment.isSearchMode()
- ? ListEvent.ListType.SEARCH_RESULT : mAllFragment.getListType();
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- // TODO: Using the new startActivityWithResultFromFragment API this should not be needed
- // anymore
- case ContactEntryListFragment.ACTIVITY_REQUEST_CODE_PICKER:
- if (resultCode == RESULT_OK) {
- mAllFragment.onPickerResult(data);
- }
- case ACTIVITY_REQUEST_CODE_SHARE:
- Logger.logListEvent(ListEvent.ActionType.SHARE,
- /* listType */ getListTypeIncludingSearch(),
- /* count */ mAllFragment.getAdapter().getCount(), /* clickedIndex */ -1,
- /* numSelected */ mAllFragment.getAdapter().getSelectedContactIds().size());
-
-// TODO fix or remove multipicker code
-// else if (resultCode == RESULT_CANCELED && mMode == MODE_PICK_MULTIPLE_PHONES) {
-// // Finish the activity if the sub activity was canceled as back key is used
-// // to confirm user selection in MODE_PICK_MULTIPLE_PHONES.
-// finish();
-// }
-// break;
- }
- }
-
- @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO move to the fragment
@@ -1160,14 +656,14 @@
// If COMBINING_ACCENT is set, it's not a unicode character.
&& ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) == 0)
&& !Character.isWhitespace(unicodeChar)) {
- if (mActionBarAdapter.isSelectionMode()) {
+ if (mAllFragment.getActionBarAdapter().isSelectionMode()) {
// Ignore keyboard input when in selection mode.
return true;
}
String query = new String(new int[]{unicodeChar}, 0, 1);
- if (!mActionBarAdapter.isSearchMode()) {
- mActionBarAdapter.setSearchMode(true);
- mActionBarAdapter.setQueryString(query);
+ if (!mAllFragment.getActionBarAdapter().isSearchMode()) {
+ mAllFragment.getActionBarAdapter().setSearchMode(true);
+ mAllFragment.getActionBarAdapter().setQueryString(query);
return true;
}
}
@@ -1183,153 +679,47 @@
if (mDrawer.isDrawerOpen(GravityCompat.START)) {
mDrawer.closeDrawer(GravityCompat.START);
- } else if (mActionBarAdapter.isSelectionMode()) {
- mActionBarAdapter.setSelectionMode(false);
+ } else if (mAllFragment.getActionBarAdapter().isSelectionMode()) {
+ mAllFragment.getActionBarAdapter().setSelectionMode(false);
mAllFragment.displayCheckBoxes(false);
- } else if (mActionBarAdapter.isSearchMode()) {
- mActionBarAdapter.setSearchMode(false);
-
+ } else if (mAllFragment.getActionBarAdapter().isSearchMode()) {
+ mAllFragment.getActionBarAdapter().setSearchMode(false);
if (mAllFragment.wasSearchResultClicked()) {
mAllFragment.resetSearchResultClicked();
} else {
Logger.logScreenView(this, ScreenType.SEARCH_EXIT);
Logger.logSearchEvent(mAllFragment.createSearchState());
}
- } else if (!isAllContactsFilter(mContactListFilterController.getFilter())) {
+ } else if (!isAllContactsFilter(mAllFragment.getFilter())) {
switchToAllContacts();
} else {
super.onBackPressed();
}
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mActionBarAdapter.onSaveInstanceState(outState);
-
- // Clear the listener to make sure we don't get callbacks after onSaveInstanceState,
- // in order to avoid doing fragment transactions after it.
- // TODO Figure out a better way to deal with the issue.
- mDisableOptionItemSelected = true;
- mActionBarAdapter.setListener(null);
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- if (mActionBarAdapter.isSearchMode()) {
- mActionBarAdapter.setFocusOnSearchView();
- }
- }
-
- @Override
- public DialogManager getDialogManager() {
- return mDialogManager;
- }
-
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.floating_action_button:
- onFabClicked();
- break;
- default:
- Log.wtf(TAG, "Unexpected onClick event from " + view);
- }
- }
-
public void onFabClicked() {
final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
- final Bundle extras = getIntent().getExtras();
- if (extras != null) {
- final ContactListFilter filter = mContactListFilterController.getFilter();
- // If we are in account view, we pass the account explicitly in order to
- // create contact in the account. This will prevent the default account dialog
- // from being displayed.
- if (!isAllContactsFilter(filter) && !isDeviceContactsFilter(filter)) {
- final Account account = new Account(filter.accountName, filter.accountType);
- extras.putParcelable(Intents.Insert.EXTRA_ACCOUNT, account);
- extras.putString(Intents.Insert.EXTRA_DATA_SET, filter.dataSet);
- }
- intent.putExtras(extras);
+ Bundle extras = getIntent().getExtras();
+ if (extras == null) {
+ extras = new Bundle();
}
+ final ContactListFilter filter = mAllFragment.getFilter();
+ // If we are in account view, we pass the account explicitly in order to
+ // create contact in the account. This will prevent the default account dialog
+ // from being displayed.
+ if (!isAllContactsFilter(filter) && !isDeviceContactsFilter(filter)) {
+ final Account account = new Account(filter.accountName, filter.accountType);
+ extras.putParcelable(Intents.Insert.EXTRA_ACCOUNT, account);
+ extras.putString(Intents.Insert.EXTRA_DATA_SET, filter.dataSet);
+ }
+ intent.putExtras(extras);
try {
ImplicitIntentsUtil.startActivityInApp(PeopleActivity.this, intent);
} catch (ActivityNotFoundException ex) {
- Toast.makeText(PeopleActivity.this, R.string.missing_app,
- Toast.LENGTH_SHORT).show();
+ Toast.makeText(PeopleActivity.this, R.string.missing_app, Toast.LENGTH_SHORT).show();
}
}
- private void setFilterAndUpdateTitle(ContactListFilter filter) {
- setFilterAndUpdateTitle(filter, true);
- }
-
- private void setFilterAndUpdateTitle(ContactListFilter filter, boolean restoreSelectedUri) {
- mAllFragment.setFilter(filter, restoreSelectedUri);
-
- mAllFragment.setListType(mContactListFilterController.getFilterListType());
-
- updateFilterMenu(filter);
-
- if (getSupportActionBar() != null) {
- String actionBarTitle;
- if (filter.filterType == ContactListFilter.FILTER_TYPE_DEVICE_CONTACTS) {
- actionBarTitle = getString(R.string.account_phone);
- } else if (!TextUtils.isEmpty(filter.accountName)) {
- actionBarTitle = getActionBarTitleForAccount(filter);
- } else {
- actionBarTitle = getString(R.string.contactsList);
- }
- getSupportActionBar().setTitle(actionBarTitle);
- if (CompatUtils.isNCompatible()) {
- this.setTitle(actionBarTitle);
- getWindow().getDecorView()
- .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- }
- }
-
- // Determine whether the account has pullToRefresh feature
- if (Flags.getInstance(this).getBoolean(Experiments.PULL_TO_REFRESH)) {
- setSwipeRefreshLayoutEnabledOrNot(filter);
- }
- }
-
- private void setSwipeRefreshLayoutEnabledOrNot(ContactListFilter filter) {
- final SwipeRefreshLayout swipeRefreshLayout = mAllFragment.getSwipeRefreshLayout();
- if (swipeRefreshLayout == null) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Can not load swipeRefreshLayout, swipeRefreshLayout is null");
- }
- return;
- }
-
- swipeRefreshLayout.setRefreshing(false);
- swipeRefreshLayout.setEnabled(false);
-
- if (filter != null && !mActionBarAdapter.isSearchMode()
- && !mActionBarAdapter.isSelectionMode()) {
- final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(this)
- .getAccounts(/* contactsWritableOnly */ true);
- if (filter.isSyncable(accounts)) {
- swipeRefreshLayout.setEnabled(true);
- }
- }
- }
-
- private String getActionBarTitleForAccount(ContactListFilter filter) {
- if (GoogleAccountType.ACCOUNT_TYPE.equals(filter.accountType)) {
- return getString(R.string.title_from_google);
- }
- return getString(R.string.title_from_other_accounts, filter.accountName);
- }
-
- // Persist filter only when it's of the type FILTER_TYPE_ALL_ACCOUNTS.
- private void persistFilterIfNeeded(ContactListFilter filter) {
- mContactListFilterController.setContactListFilter(filter,
- /* persistent */ isAllContactsFilter(filter));
- }
-
private boolean isAllContactsFilter(ContactListFilter filter) {
return filter != null && filter.isContactsFilterType();
}
@@ -1345,12 +735,7 @@
@Override
protected ContactListFilter getContactListFilter() {
- return mContactListFilterController.getFilter();
- }
-
- @Override
- public void onLoadFinishedCallback() {
- maybeShowHamburgerFeatureHighlight();
+ return mAllFragment.getFilter();
}
private void onGroupDeleted(Intent intent) {
diff --git a/src/com/android/contacts/common/util/AccountFilterUtil.java b/src/com/android/contacts/common/util/AccountFilterUtil.java
index 76975a6..66bffdc 100644
--- a/src/com/android/contacts/common/util/AccountFilterUtil.java
+++ b/src/com/android/contacts/common/util/AccountFilterUtil.java
@@ -162,4 +162,17 @@
return null;
}
}
+
+ /**
+ * Returns a {@link ContactListFilter} of type
+ * {@link ContactListFilter#FILTER_TYPE_ALL_ACCOUNTS}, or if a custom "Contacts to display"
+ * filter has been set, then one of type {@link ContactListFilter#FILTER_TYPE_CUSTOM}.
+ */
+ public static ContactListFilter createContactsFilter(Context context) {
+ final int filterType =
+ ContactListFilterController.getInstance(context).isCustomFilterPersisted()
+ ? ContactListFilter.FILTER_TYPE_CUSTOM
+ : ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS;
+ return ContactListFilter.createFilterWithType(filterType);
+ }
}
diff --git a/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java b/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
index 173f66e..ff0d978 100644
--- a/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
+++ b/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
@@ -75,21 +75,22 @@
private TreeSet<Long> mContactIds;
private Context mContext;
private AlertDialog mDialog;
+ private MultiContactDeleteListener mListener;
/**
* Starts the interaction.
*
- * @param activity the activity within which to start the interaction
+ * @param hostFragment the fragment within which to start the interaction
* @param contactIds the IDs of contacts to be deleted
* @return the newly created interaction
*/
public static ContactMultiDeletionInteraction start(
- Activity activity, TreeSet<Long> contactIds) {
+ Fragment hostFragment, TreeSet<Long> contactIds) {
if (contactIds == null) {
return null;
}
- final FragmentManager fragmentManager = activity.getFragmentManager();
+ final FragmentManager fragmentManager = hostFragment.getFragmentManager();
ContactMultiDeletionInteraction fragment =
(ContactMultiDeletionInteraction) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
if (fragment == null) {
@@ -291,13 +292,10 @@
protected void doDeleteContact(long[] contactIds) {
mContext.startService(ContactSaveService.createDeleteMultipleContactsIntent(mContext,
contactIds));
- notifyListenerActivity();
+ mListener.onDeletionFinished();
}
- private void notifyListenerActivity() {
- if (getActivity() instanceof MultiContactDeleteListener) {
- final MultiContactDeleteListener listener = (MultiContactDeleteListener) getActivity();
- listener.onDeletionFinished();
- }
+ public void setListener(MultiContactDeleteListener listener) {
+ mListener = listener;
}
}
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index da33b55..262856c 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -680,9 +680,4 @@
return mPersistentSelectionPrefix + "-" + mFilter.getId();
}
}
-
- public boolean isOptionsMenuChanged() {
- // This fragment does not have an option menu of its own
- return false;
- }
}
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index a25e769..7428e7a 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -16,19 +16,31 @@
package com.android.contacts.list;
import android.accounts.Account;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
+import android.content.Intent;
import android.content.Loader;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.database.Cursor;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Directory;
+import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.TextUtils;
+import android.util.Log;
import android.view.Gravity;
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.view.accessibility.AccessibilityEvent;
@@ -37,27 +49,56 @@
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
+import android.widget.Toast;
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.ContactsDrawerActivity;
import com.android.contacts.R;
+import com.android.contacts.activities.ActionBarAdapter;
import com.android.contacts.activities.PeopleActivity;
import com.android.contacts.common.Experiments;
+import com.android.contacts.common.compat.CompatUtils;
+import com.android.contacts.common.list.ContactEntryListFragment;
import com.android.contacts.common.list.ContactListAdapter;
import com.android.contacts.common.list.ContactListFilter;
+import com.android.contacts.common.list.ContactListFilterController;
+import com.android.contacts.common.list.ContactListFilterController.ContactListFilterListener;
import com.android.contacts.common.list.ContactListItemView;
import com.android.contacts.common.list.DefaultContactListAdapter;
import com.android.contacts.common.list.FavoritesAndContactsLoader;
+import com.android.contacts.common.logging.ListEvent;
+import com.android.contacts.common.logging.Logger;
+import com.android.contacts.common.logging.ScreenEvent;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.android.contacts.common.model.account.GoogleAccountType;
+import com.android.contacts.common.util.AccountFilterUtil;
+import com.android.contacts.common.util.ImplicitIntentsUtil;
+import com.android.contacts.interactions.ContactDeletionInteraction;
+import com.android.contacts.interactions.ContactMultiDeletionInteraction;
+import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
+import com.android.contacts.quickcontact.QuickContactActivity;
+import com.android.contacts.util.SharedPreferenceUtil;
import com.android.contacts.util.SyncUtil;
import com.android.contactsbind.experiments.Flags;
+import com.google.android.libraries.material.featurehighlight.FeatureHighlight;
+
import java.util.List;
+import java.util.Locale;
/**
* Fragment containing a contact list used for browsing (as compared to
* picking a contact with one of the PICK intents).
*/
public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
+
+ private static final String TAG = "DefaultListFragment";
+ private static final String ENABLE_DEBUG_OPTIONS_HIDDEN_CODE = "debug debug!";
+ private static final String KEY_DELETION_IN_PROGRESS = "deletionInProgress";
+
+ private static final int ACTIVITY_REQUEST_CODE_SHARE = 0;
+
private View mSearchHeaderView;
private View mSearchProgress;
private View mEmptyAccountView;
@@ -65,11 +106,114 @@
private View mAccountFilterContainer;
private TextView mSearchProgressText;
private SwipeRefreshLayout mSwipeRefreshLayout;
- private FeatureHighlightCallback mCallback;
- public interface FeatureHighlightCallback {
- void onLoadFinishedCallback();
- }
+ private boolean mContactsAvailable;
+ private boolean mEnableDebugMenuOptions;
+ private boolean mIsRecreatedInstance;
+ private boolean mOptionsMenuContactsAvailable;
+
+ /**
+ * This is to tell whether we need to restart ContactMultiDeletionInteraction and set listener.
+ * if screen is rotated while deletion dialog is shown.
+ */
+ private boolean mIsDeletionInProgress;
+
+ /**
+ * This is to disable {@link #onOptionsItemSelected} when we trying to stop the
+ * activity/fragment.
+ */
+ private boolean mDisableOptionItemSelected;
+
+ private ActionBarAdapter mActionBarAdapter;
+ private ContactMultiDeletionInteraction mMultiDeletionInteraction;
+ private ContactsRequest mContactsRequest;
+ protected ContactListFilterController mContactListFilterController;
+
+ private final ContactListFilterListener mFilterListener = new ContactListFilterListener() {
+ @Override
+ public void onContactListFilterChanged() {
+ final ContactListFilter filter = mContactListFilterController.getFilter();
+ setFilterAndUpdateTitle(filter);
+
+ // Scroll to top after filter is changed.
+ getListView().setSelection(0);
+
+ getActivity().invalidateOptionsMenu();
+ }
+ };
+
+ private final ActionBarAdapter.Listener mActionBarListener = new ActionBarAdapter.Listener() {
+ @Override
+ public void onAction(int action) {
+ switch (action) {
+ case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
+ displayCheckBoxes(true);
+ startSearchOrSelectionMode();
+ break;
+ case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
+ if (!mIsRecreatedInstance) {
+ Logger.logScreenView(getActivity(), ScreenEvent.ScreenType.SEARCH);
+ }
+ startSearchOrSelectionMode();
+ break;
+ case ActionBarAdapter.Listener.Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE:
+ ((PeopleActivity) getActivity()).showFabWithAnimation(/* showFab */ true);
+ break;
+ case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
+ // If queryString is empty, fragment data will not be reloaded,
+ // so hamburger promo should be checked now.
+ // Otherwise, promo should be checked and displayed after reloading, b/30706521.
+ if (TextUtils.isEmpty(getQueryString())) {
+ maybeShowHamburgerFeatureHighlight();
+ }
+ setQueryTextToFragment("");
+ maybeHideCheckBoxes();
+ getActivity().invalidateOptionsMenu();
+ ((PeopleActivity) getActivity()).showFabWithAnimation(/* showFab */ true);
+ // Determine whether the account has pullToRefresh feature
+ if (Flags.getInstance(getContext()).getBoolean(Experiments.PULL_TO_REFRESH)) {
+ setSwipeRefreshLayoutEnabledOrNot(getFilter());
+ }
+ break;
+ case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
+ final String queryString = mActionBarAdapter.getQueryString();
+ setQueryTextToFragment(queryString);
+ updateDebugOptionsVisibility(
+ ENABLE_DEBUG_OPTIONS_HIDDEN_CODE.equals(queryString));
+ break;
+ default:
+ throw new IllegalStateException("Unknown ActionBarAdapter action: " + action);
+ }
+ }
+
+ private void startSearchOrSelectionMode() {
+ configureContactListFragment();
+ maybeHideCheckBoxes();
+ getActivity().invalidateOptionsMenu();
+ ((PeopleActivity) getActivity()).showFabWithAnimation(/* showFab */ false);
+ final Context context = getContext();
+ if (!SharedPreferenceUtil.getHamburgerPromoTriggerActionHappenedBefore(context)) {
+ SharedPreferenceUtil.setHamburgerPromoTriggerActionHappenedBefore(context);
+ }
+ }
+
+ private void updateDebugOptionsVisibility(boolean visible) {
+ if (mEnableDebugMenuOptions != visible) {
+ mEnableDebugMenuOptions = visible;
+ getActivity().invalidateOptionsMenu();
+ }
+ }
+
+ private void setQueryTextToFragment(String query) {
+ setQueryString(query, true);
+ setVisibleScrollbarEnabled(!isSearchMode());
+ }
+
+ @Override
+ public void onUpButtonPressed() {
+ getActivity().onBackPressed();
+ }
+ };
public DefaultContactBrowseListFragment() {
setPhotoLoaderEnabled(true);
@@ -79,10 +223,7 @@
setSectionHeaderDisplayEnabled(true);
setVisibleScrollbarEnabled(true);
setDisplayDirectoryHeader(false);
- }
-
- public void setFeatureHighlightCallback(FeatureHighlightCallback callback) {
- mCallback = callback;
+ setHasOptionsMenu(true);
}
@Override
@@ -96,8 +237,21 @@
bindListHeader(data.getCount());
}
super.onLoadFinished(loader, data);
- if (!isSearchMode() && mCallback != null) {
- mCallback.onLoadFinishedCallback();
+ if (!isSearchMode()) {
+ maybeShowHamburgerFeatureHighlight();
+ }
+ }
+
+ public void maybeShowHamburgerFeatureHighlight() {
+ if (mActionBarAdapter != null && !mActionBarAdapter.isSearchMode()
+ && !mActionBarAdapter.isSelectionMode()
+ && SharedPreferenceUtil.getShouldShowHamburgerPromo(getContext())) {
+ final FeatureHighlight hamburgerFeatureHighlight =
+ mActionBarAdapter.getHamburgerFeatureHighlight();
+ if (hamburgerFeatureHighlight != null) {
+ hamburgerFeatureHighlight.show((FragmentActivity) getActivity());
+ SharedPreferenceUtil.setHamburgerPromoDisplayedBefore(getContext());
+ }
}
}
@@ -263,11 +417,10 @@
if (Flags.getInstance(getActivity()).getBoolean(Experiments.PULL_TO_REFRESH)) {
initSwipeRefreshLayout();
-
}
// Putting the header view inside a container will allow us to make
// it invisible later. See checkHeaderViewVisibility()
- FrameLayout headerContainer = new FrameLayout(inflater.getContext());
+ final FrameLayout headerContainer = new FrameLayout(inflater.getContext());
mSearchHeaderView = inflater.inflate(R.layout.search_header, null, false);
headerContainer.addView(mSearchHeaderView);
getListView().addHeaderView(headerContainer, null, false);
@@ -317,7 +470,7 @@
final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts);
if (syncableAccounts != null && syncableAccounts.size() > 0) {
for (Account account : syncableAccounts) {
- // We can prioritize Contacts sync if sync is not initialized yet.
+ // We can prioritize Contacts sync if sync is not initialized yet.
if (!SyncUtil.isSyncStatusPendingOrActive(account)
|| SyncUtil.isUnsyncableGoogleAccount(account)) {
ContentResolver.requestSync(account, ContactsContract.AUTHORITY, bundle);
@@ -327,6 +480,64 @@
}
@Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mIsRecreatedInstance = (savedInstanceState != null);
+ mContactListFilterController = ContactListFilterController.getInstance(getContext());
+ mContactListFilterController.checkFilterValidity(false);
+ mContactListFilterController.addListener(mFilterListener);
+
+ // Use FILTER_TYPE_ALL_ACCOUNTS filter if the instance is not a re-created one.
+ // This is useful when user upgrades app while an account filter or a custom filter was
+ // stored in sharedPreference in a previous version of Contacts app.
+ final ContactListFilter filter = mIsRecreatedInstance
+ ? mContactListFilterController.getFilter()
+ : AccountFilterUtil.createContactsFilter(getContext());
+ setContactListFilter(filter);
+
+ final ContactsDrawerActivity activity = (ContactsDrawerActivity) getActivity();
+ mActionBarAdapter = new ActionBarAdapter(activity, mActionBarListener,
+ activity.getSupportActionBar(), activity.getToolbar(), R.string.enter_contact_name);
+ mActionBarAdapter.setShowHomeIcon(true);
+ initializeActionBarAdapter(savedInstanceState);
+ if (isSearchMode()) {
+ mActionBarAdapter.setFocusOnSearchView();
+ }
+
+ setCheckBoxListListener(new CheckBoxListListener());
+ setOnContactListActionListener(new ContactBrowserActionListener());
+ if (mIsRecreatedInstance && savedInstanceState.getBoolean(KEY_DELETION_IN_PROGRESS)) {
+ deleteSelectedContacts();
+ }
+ }
+
+ public void initializeActionBarAdapter(Bundle savedInstanceState) {
+ if (mActionBarAdapter != null) {
+ mActionBarAdapter.initialize(savedInstanceState, mContactsRequest);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Re-register the listener, which may have been cleared when onSaveInstanceState was
+ // called. See also: onSaveInstanceState
+ mActionBarAdapter.setListener(mActionBarListener);
+ mDisableOptionItemSelected = false;
+ maybeHideCheckBoxes();
+ }
+
+ private void maybeHideCheckBoxes() {
+ if (!mActionBarAdapter.isSelectionMode()) {
+ displayCheckBoxes(false);
+ }
+ }
+
+ public ActionBarAdapter getActionBarAdapter(){
+ return mActionBarAdapter;
+ }
+
+ @Override
protected void setSearchMode(boolean flag) {
super.setSearchMode(flag);
checkHeaderViewVisibility();
@@ -378,4 +589,423 @@
public SwipeRefreshLayout getSwipeRefreshLayout() {
return mSwipeRefreshLayout;
}
+
+ private final class CheckBoxListListener implements OnCheckBoxListActionListener {
+ @Override
+ public void onStartDisplayingCheckBoxes() {
+ mActionBarAdapter.setSelectionMode(true);
+ getActivity().invalidateOptionsMenu();
+ }
+
+ @Override
+ public void onSelectedContactIdsChanged() {
+ mActionBarAdapter.setSelectionCount(getSelectedContactIds().size());
+ getActivity().invalidateOptionsMenu();
+ }
+
+ @Override
+ public void onStopDisplayingCheckBoxes() {
+ mActionBarAdapter.setSelectionMode(false);
+ }
+ }
+
+ private void setFilterAndUpdateTitle(ContactListFilter filter) {
+ setFilterAndUpdateTitle(filter, true);
+ }
+
+ private void setFilterAndUpdateTitle(ContactListFilter filter, boolean restoreSelectedUri) {
+ setFilter(filter, restoreSelectedUri);
+ setListType(mContactListFilterController.getFilterListType());
+
+ ((ContactsDrawerActivity) getActivity()).updateFilterMenu(filter);
+
+ final String actionBarTitle;
+ if (filter.filterType == ContactListFilter.FILTER_TYPE_DEVICE_CONTACTS) {
+ actionBarTitle = getString(R.string.account_phone);
+ } else if (!TextUtils.isEmpty(filter.accountName)) {
+ actionBarTitle = getActionBarTitleForAccount(filter);
+ } else {
+ actionBarTitle = getString(R.string.contactsList);
+ }
+ getActivity().setTitle(actionBarTitle);
+
+ if (CompatUtils.isNCompatible()) {
+ getActivity().setTitle(actionBarTitle);
+ getActivity().getWindow().getDecorView()
+ .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+ // Determine whether the account has pullToRefresh feature
+ if (Flags.getInstance(getContext()).getBoolean(Experiments.PULL_TO_REFRESH)) {
+ setSwipeRefreshLayoutEnabledOrNot(filter);
+ }
+ }
+
+ private String getActionBarTitleForAccount(ContactListFilter filter) {
+ if (GoogleAccountType.ACCOUNT_TYPE.equals(filter.accountType)) {
+ return getString(R.string.title_from_google);
+ }
+ return getString(R.string.title_from_other_accounts, filter.accountName);
+ }
+
+ public void setSwipeRefreshLayoutEnabledOrNot(ContactListFilter filter) {
+ final SwipeRefreshLayout swipeRefreshLayout = getSwipeRefreshLayout();
+ if (swipeRefreshLayout == null) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Can not load swipeRefreshLayout, swipeRefreshLayout is null");
+ }
+ return;
+ }
+
+ swipeRefreshLayout.setRefreshing(false);
+ swipeRefreshLayout.setEnabled(false);
+
+ if (filter != null && !mActionBarAdapter.isSearchMode()
+ && !mActionBarAdapter.isSelectionMode()) {
+ final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(getContext())
+ .getAccounts(/* contactsWritableOnly */ true);
+ if (filter.isSyncable(accounts)) {
+ swipeRefreshLayout.setEnabled(true);
+ }
+ }
+ }
+
+ public void configureContactListFragment() {
+ // Filter may be changed when activity is in background.
+ setFilterAndUpdateTitle(getFilter());
+ setVerticalScrollbarPosition(getScrollBarPosition());
+ setSelectionVisible(false);
+ getActivity().invalidateOptionsMenu();
+ }
+
+ private int getScrollBarPosition() {
+ final Locale locale = Locale.getDefault();
+ final boolean isRTL =
+ TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
+ return isRTL ? View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
+ }
+
+ private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
+ ContactBrowserActionListener() {}
+
+ @Override
+ public void onSelectionChange() {
+
+ }
+
+ @Override
+ public void onViewContactAction(int position, Uri contactLookupUri,
+ boolean isEnterpriseContact) {
+ if (isEnterpriseContact) {
+ // No implicit intent as user may have a different contacts app in work profile.
+ ContactsContract.QuickContact.showQuickContact(getContext(), new Rect(),
+ contactLookupUri, QuickContactActivity.MODE_FULLY_EXPANDED, null);
+ } else {
+ final Intent intent = ImplicitIntentsUtil.composeQuickContactIntent(
+ getContext(), contactLookupUri, QuickContactActivity.MODE_FULLY_EXPANDED);
+ final int previousScreen;
+ if (isSearchMode()) {
+ previousScreen = ScreenEvent.ScreenType.SEARCH;
+ } else {
+ if (isAllContactsFilter(mContactListFilterController.getFilter())) {
+ if (position < getAdapter().getNumberOfFavorites()) {
+ previousScreen = ScreenEvent.ScreenType.FAVORITES;
+ } else {
+ previousScreen = ScreenEvent.ScreenType.ALL_CONTACTS;
+ }
+ } else {
+ previousScreen = ScreenEvent.ScreenType.LIST_ACCOUNT;
+ }
+ }
+ Logger.logListEvent(ListEvent.ActionType.CLICK,
+ /* listType */ getListTypeIncludingSearch(),
+ /* count */ getAdapter().getCount(),
+ /* clickedIndex */ position, /* numSelected */ 0);
+ intent.putExtra(QuickContactActivity.EXTRA_PREVIOUS_SCREEN_TYPE, previousScreen);
+ ImplicitIntentsUtil.startActivityInApp(getContext(), intent);
+ }
+ }
+
+ @Override
+ public void onDeleteContactAction(Uri contactUri) {
+ ContactDeletionInteraction.start(getActivity(), contactUri, false);
+ }
+
+ @Override
+ public void onFinishAction() {
+ getActivity().onBackPressed();
+ }
+
+ @Override
+ public void onInvalidSelection() {
+ ContactListFilter filter;
+ ContactListFilter currentFilter = getFilter();
+ if (currentFilter != null
+ && currentFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
+ filter = AccountFilterUtil.createContactsFilter(getContext());
+ setFilterAndUpdateTitle(filter);
+ } else {
+ filter = ContactListFilter.createFilterWithType(
+ ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
+ setFilterAndUpdateTitle(filter, /* restoreSelectedUri */ false);
+ }
+ setContactListFilter(filter);
+ }
+ }
+
+ private boolean isAllContactsFilter(ContactListFilter filter) {
+ return filter != null && filter.isContactsFilterType();
+ }
+
+ public void setContactsAvailable(boolean contactsAvailable) {
+ mContactsAvailable = contactsAvailable;
+ }
+
+ /**
+ * Set filter via ContactListFilterController
+ */
+ public void setContactListFilter(ContactListFilter filter) {
+ mContactListFilterController.setContactListFilter(filter,
+ /* persistent */ isAllContactsFilter(filter));
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (!mContactsAvailable) {
+ // If contacts aren't available, hide all menu items.
+ return;
+ }
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.people_options, menu);
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ mOptionsMenuContactsAvailable = mContactsAvailable;
+ if (!mOptionsMenuContactsAvailable) {
+ return;
+ }
+
+ final boolean isSearchOrSelectionMode = mActionBarAdapter.isSearchMode()
+ || mActionBarAdapter.isSelectionMode();
+ makeMenuItemVisible(menu, R.id.menu_search, !isSearchOrSelectionMode);
+
+ final boolean showSelectedContactOptions = mActionBarAdapter.isSelectionMode()
+ && getSelectedContactIds().size() != 0;
+ makeMenuItemVisible(menu, R.id.menu_share, showSelectedContactOptions);
+ makeMenuItemVisible(menu, R.id.menu_delete, showSelectedContactOptions);
+ final boolean showLinkContactsOptions = mActionBarAdapter.isSelectionMode()
+ && getSelectedContactIds().size() > 1;
+ makeMenuItemVisible(menu, R.id.menu_join, showLinkContactsOptions);
+
+ // Debug options need to be visible even in search mode.
+ makeMenuItemVisible(menu, R.id.export_database, mEnableDebugMenuOptions &&
+ hasExportIntentHandler());
+ }
+
+ private void makeMenuItemVisible(Menu menu, int itemId, boolean visible) {
+ final MenuItem item = menu.findItem(itemId);
+ if (item != null) {
+ item.setVisible(visible);
+ }
+ }
+
+ private boolean hasExportIntentHandler() {
+ final Intent intent = new Intent();
+ intent.setAction("com.android.providers.contacts.DUMP_DATABASE");
+ final List<ResolveInfo> receivers =
+ getContext().getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ return receivers != null && receivers.size() > 0;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mDisableOptionItemSelected) {
+ return false;
+ }
+
+ switch (item.getItemId()) {
+ case android.R.id.home: {
+ // The home icon on the action bar is pressed
+ if (mActionBarAdapter.isUpShowing()) {
+ // "UP" icon press -- should be treated as "back".
+ getActivity().onBackPressed();
+ }
+ return true;
+ }
+ case R.id.menu_search: {
+ if (!mActionBarAdapter.isSelectionMode()) {
+ mActionBarAdapter.setSearchMode(true);
+ }
+ return true;
+ }
+ case R.id.menu_share: {
+ shareSelectedContacts();
+ return true;
+ }
+ case R.id.menu_join: {
+ Logger.logListEvent(ListEvent.ActionType.LINK,
+ /* listType */ getListTypeIncludingSearch(),
+ /* count */ getAdapter().getCount(), /* clickedIndex */ -1,
+ /* numSelected */ getAdapter().getSelectedContactIds().size());
+ joinSelectedContacts();
+ return true;
+ }
+ case R.id.menu_delete: {
+ deleteSelectedContacts();
+ return true;
+ }
+ case R.id.export_database: {
+ final Intent intent = new Intent("com.android.providers.contacts.DUMP_DATABASE");
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ ImplicitIntentsUtil.startActivityOutsideApp(getContext(), intent);
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Share all contacts that are currently selected in mAllFragment. This method is pretty
+ * inefficient for handling large numbers of contacts. I don't expect this to be a problem.
+ */
+ private void shareSelectedContacts() {
+ final StringBuilder uriListBuilder = new StringBuilder();
+ for (Long contactId : getSelectedContactIds()) {
+ final Uri contactUri = ContentUris.withAppendedId(
+ ContactsContract.Contacts.CONTENT_URI, contactId);
+ final Uri lookupUri = ContactsContract.Contacts.getLookupUri(
+ getContext().getContentResolver(), contactUri);
+ if (lookupUri == null) {
+ continue;
+ }
+ final List<String> pathSegments = lookupUri.getPathSegments();
+ if (pathSegments.size() < 2) {
+ continue;
+ }
+ final String lookupKey = pathSegments.get(pathSegments.size() - 2);
+ if (uriListBuilder.length() > 0) {
+ uriListBuilder.append(':');
+ }
+ uriListBuilder.append(Uri.encode(lookupKey));
+ }
+ if (uriListBuilder.length() == 0) {
+ return;
+ }
+ final Uri uri = Uri.withAppendedPath(
+ ContactsContract.Contacts.CONTENT_MULTI_VCARD_URI,
+ Uri.encode(uriListBuilder.toString()));
+ final Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(ContactsContract.Contacts.CONTENT_VCARD_TYPE);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ try {
+ startActivityForResult(Intent.createChooser(intent, getResources().getQuantityString(
+ R.plurals.title_share_via,/* quantity */ getSelectedContactIds().size()))
+ , ACTIVITY_REQUEST_CODE_SHARE);
+ } catch (final ActivityNotFoundException ex) {
+ Toast.makeText(getContext(), R.string.share_error, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private void joinSelectedContacts() {
+ final Context context = getContext();
+ final Intent intent = ContactSaveService.createJoinSeveralContactsIntent(
+ context, getSelectedContactIdsArray());
+ context.startService(intent);
+
+ mActionBarAdapter.setSelectionMode(false);
+ }
+
+ private void deleteSelectedContacts() {
+ mMultiDeletionInteraction =
+ ContactMultiDeletionInteraction.start(this, getSelectedContactIds());
+ mMultiDeletionInteraction.setListener(new MultiDeleteListener());
+ mIsDeletionInProgress = true;
+ }
+
+ private final class MultiDeleteListener implements MultiContactDeleteListener {
+ @Override
+ public void onDeletionFinished() {
+ // The parameters count and numSelected are both the number of contacts before deletion.
+ Logger.logListEvent(ListEvent.ActionType.DELETE,
+ /* listType */ getListTypeIncludingSearch(),
+ /* count */ getAdapter().getCount(), /* clickedIndex */ -1,
+ /* numSelected */ getSelectedContactIds().size());
+ mActionBarAdapter.setSelectionMode(false);
+ mIsDeletionInProgress = false;
+ }
+ }
+
+ private int getListTypeIncludingSearch() {
+ return isSearchMode() ? ListEvent.ListType.SEARCH_RESULT : getListType();
+ }
+
+ public void setListType() {
+ mContactListFilterController = ContactListFilterController.getInstance(getContext());
+ setListType(mContactListFilterController.getFilterListType());
+ }
+
+ public void setContactsRequest(ContactsRequest contactsRequest) {
+ mContactsRequest = contactsRequest;
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ // TODO: Using the new startActivityWithResultFromFragment API this should not be needed
+ // anymore
+ case ContactEntryListFragment.ACTIVITY_REQUEST_CODE_PICKER:
+ if (resultCode == Activity.RESULT_OK) {
+ onPickerResult(data);
+ }
+ case ACTIVITY_REQUEST_CODE_SHARE:
+ Logger.logListEvent(ListEvent.ActionType.SHARE,
+ /* listType */ getListTypeIncludingSearch(),
+ /* count */ getAdapter().getCount(), /* clickedIndex */ -1,
+ /* numSelected */ getAdapter().getSelectedContactIds().size());
+
+// TODO fix or remove multipicker code: ag/54762
+// else if (resultCode == RESULT_CANCELED && mMode == MODE_PICK_MULTIPLE_PHONES) {
+// // Finish the activity if the sub activity was canceled as back key is used
+// // to confirm user selection in MODE_PICK_MULTIPLE_PHONES.
+// finish();
+// }
+// break;
+ }
+ }
+
+ public boolean getOptionsMenuContactsAvailable() {
+ return mOptionsMenuContactsAvailable;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // Clear the listener to make sure we don't get callbacks after onSaveInstanceState,
+ // in order to avoid doing fragment transactions after it.
+ // TODO Figure out a better way to deal with the issue (ag/120686).
+ if (mActionBarAdapter != null) {
+ mActionBarAdapter.setListener(null);
+ mActionBarAdapter.onSaveInstanceState(outState);
+ }
+ mDisableOptionItemSelected = true;
+ outState.putBoolean(KEY_DELETION_IN_PROGRESS, mIsDeletionInProgress);
+ }
+
+ @Override
+ public void onPause() {
+ mOptionsMenuContactsAvailable = false;
+ super.onPause();
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mActionBarAdapter != null) {
+ mActionBarAdapter.setListener(null);
+ }
+ if (mContactListFilterController != null) {
+ mContactListFilterController.removeListener(mFilterListener);
+ }
+ super.onDestroy();
+ }
}