Merge "Moving state machine logic from activity into fragment."
diff --git a/src/com/android/contacts/activities/ContactBrowserActivity.java b/src/com/android/contacts/activities/ContactBrowserActivity.java
index c72f0d8..4d56be3 100644
--- a/src/com/android/contacts/activities/ContactBrowserActivity.java
+++ b/src/com/android/contacts/activities/ContactBrowserActivity.java
@@ -54,12 +54,8 @@
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
@@ -99,23 +95,6 @@
private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20;
- /**
- * The id for a delayed message that triggers automatic selection of the first
- * found contact in search mode.
- */
- private static final int MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT = 1;
-
- /**
- * The delay that is used for automatically selecting the first found contact.
- */
- private static final int DELAY_AUTOSELECT_FIRST_FOUND_CONTACT_MILLIS = 500;
-
- /**
- * The minimum number of characters in the search query that is required
- * before we automatically select the first found contact.
- */
- private static final int AUTOSELECT_FIRST_FOUND_CONTACT_MIN_QUERY_LENGTH = 2;
-
private static final String KEY_SEARCH_MODE = "searchMode";
private DialogManager mDialogManager = new DialogManager(this);
@@ -123,8 +102,6 @@
private ContactsIntentResolver mIntentResolver;
private ContactsRequest mRequest;
- private SharedPreferences mPrefs;
-
private boolean mHasActionBar;
private ActionBarAdapter mActionBarAdapter;
@@ -146,8 +123,6 @@
private ImageButton mAddContactImageView;
- private Handler mHandler;
-
private ContactsUnavailableFragment mContactsUnavailableFragment;
private ProviderStatusLoader mProviderStatusLoader;
private int mProviderStatus = -1;
@@ -159,20 +134,6 @@
mProviderStatusLoader = new ProviderStatusLoader(this);
}
- private Handler getHandler() {
- if (mHandler == null) {
- mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT) {
- selectFirstFoundContact();
- }
- }
- };
- }
- return mHandler;
- }
-
public boolean areContactsAvailable() {
return mProviderStatus == ProviderStatus.STATUS_NORMAL;
}
@@ -182,7 +143,6 @@
if (fragment instanceof ContactBrowseListFragment) {
mListFragment = (ContactBrowseListFragment)fragment;
mListFragment.setOnContactListActionListener(new ContactBrowserActionListener());
- configureListSelection();
} else if (fragment instanceof ContactDetailFragment) {
mDetailFragment = (ContactDetailFragment)fragment;
mDetailFragment.setListener(mDetailFragmentListener);
@@ -218,8 +178,6 @@
return;
}
- mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
-
setTitle(mRequest.getActivityTitle());
setContentView(R.layout.contact_browser);
@@ -268,18 +226,10 @@
if (mHasActionBar) {
mActionBarAdapter.setSearchMode(false);
-
- // onNewIntent is called when the activity is paused, so it is not
- // registered as a listener of the action bar adapter. Simulate the listener call.
- onAction();
+ configureFragments(false /* from request */);
}
mListFragment.setSelectedContactUri(uri);
- mListFragment.saveSelectedUri(mPrefs);
- mListFragment.requestSelectionOnScreen(true);
- if (mContactContentDisplayed) {
- setupContactDetailFragment(uri);
- }
}
}
@@ -338,6 +288,11 @@
mContactListFilterController.setContactListFilter(new ContactListFilter(
ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS), false);
}
+
+ if (mRequest.getContactUri() != null) {
+ searchMode = false;
+ }
+
} else if (mHasActionBar) {
searchMode = mActionBarAdapter.isSearchMode();
}
@@ -352,19 +307,17 @@
if (mSearchMode) {
mListFragment = createContactSearchFragment();
- // When switching to the search mode, erase previous state of the search UI
- mListFragment.eraseSelectedUri(mPrefs);
} else {
mListFragment = createListFragment(ContactsRequest.ACTION_DEFAULT);
+ if (mRequest.getContactUri() != null) {
+ mListFragment.setSelectedContactUri(mRequest.getContactUri());
+
+ }
}
}
- if (mSearchMode) {
- if (mHasActionBar) {
- mListFragment.setQueryString(mActionBarAdapter.getQueryString());
- }
- } else {
- configureListSelection();
+ if (mSearchMode && mHasActionBar) {
+ mListFragment.setQueryString(mActionBarAdapter.getQueryString());
}
if (replaceList) {
@@ -372,155 +325,40 @@
.replace(R.id.list_container, mListFragment)
.commit();
}
+
+ if (mContactContentDisplayed && mDetailFragment == null) {
+ mDetailFragment = new ContactDetailFragment();
+ getFragmentManager().openTransaction()
+ .replace(R.id.detail_container, mDetailFragment)
+ .commit();
+ }
}
@Override
public void onContactListFiltersLoaded() {
- configureListSelection();
+ if (mListFragment == null) {
+ return;
+ }
+
+ mListFragment.setFilter(mContactListFilterController.getFilter());
// Filters have been loaded - now we can start loading the list itself
mListFragment.startLoading();
+
+ invalidateOptionsMenu();
}
@Override
public void onContactListFilterChanged() {
- resetContactSelectionInIntent();
-
if (mListFragment == null) {
return;
}
- DefaultContactBrowseListFragment fragment =
- (DefaultContactBrowseListFragment) mListFragment;
- ContactListFilter filter = mContactListFilterController.getFilter();
- fragment.setFilter(filter);
- fragment.reloadData();
- fragment.restoreSelectedUri(mPrefs);
- fragment.requestSelectionOnScreen(false);
-
- if (mContactContentDisplayed) {
- setupContactDetailFragment(mListFragment.getSelectedContactUri());
- }
+ mListFragment.setFilter(mContactListFilterController.getFilter());
invalidateOptionsMenu();
}
- /**
- * Configures filter-specific persistent selection.
- */
- private void configureListSelection() {
- if (mListFragment == null) {
- return;
- }
-
- if (mListFragment instanceof DefaultContactBrowseListFragment
- && mContactListFilterController != null
- && mContactListFilterController.isLoaded()) {
- DefaultContactBrowseListFragment fragment =
- (DefaultContactBrowseListFragment) mListFragment;
- ContactListFilter filter = mContactListFilterController.getFilter();
- fragment.setFilter(filter);
- if (mRequest.getContactUri() != null) {
- fragment.setSelectedContactUri(mRequest.getContactUri());
- fragment.saveSelectedUri(mPrefs);
- } else {
- fragment.restoreSelectedUri(mPrefs);
- }
- fragment.requestSelectionOnScreen(false);
- if (mContactContentDisplayed) {
- setupContactDetailFragment(mListFragment.getSelectedContactUri());
- }
- } else if (mContactContentDisplayed) {
- setupContactDetailFragment(mListFragment.getSelectedContactUri());
- }
-
- invalidateOptionsMenu();
- }
-
- /**
- * Removes the selected contact URI that was supplied with the intent (if any),
- * because the user has explicitly changed the selection.
- */
- private void resetContactSelectionInIntent() {
- mRequest.setContactUri(null);
-
- getIntent().setAction(Intent.ACTION_DEFAULT);
- getIntent().setData(null);
- }
-
- private void showDefaultSelection() {
- if (mSearchMode) {
- selectFirstFoundContactAfterDelay();
- return;
- }
-
- Uri requestedContactUri = mRequest.getContactUri();
- if (requestedContactUri != null
- && mListFragment instanceof DefaultContactBrowseListFragment) {
- // If a specific selection was requested, adjust the filter so
- // that the requested selection is unconditionally visible.
- DefaultContactBrowseListFragment fragment =
- (DefaultContactBrowseListFragment) mListFragment;
- ContactListFilter filter =
- new ContactListFilter(ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
- fragment.setFilter(filter);
- fragment.setSelectedContactUri(requestedContactUri);
- fragment.saveSelectedUri(mPrefs);
- fragment.reloadData();
- if (mContactListFilterController != null) {
- mContactListFilterController.setContactListFilter(filter, true);
- }
- } else {
- // Otherwise, choose the first contact on the list and select it
- requestedContactUri = mListFragment.getFirstContactUri();
- if (requestedContactUri != null) {
- mListFragment.setSelectedContactUri(requestedContactUri);
- mListFragment.eraseSelectedUri(mPrefs);
- mListFragment.requestSelectionOnScreen(false);
- }
- }
- if (mContactContentDisplayed) {
- setupContactDetailFragment(requestedContactUri);
- }
-
- invalidateOptionsMenu();
- }
-
- /**
- * Automatically selects the first found contact in search mode. The selection
- * is updated after a delay to allow the user to type without to much UI churn
- * and to save bandwidth on directory queries.
- */
- public void selectFirstFoundContactAfterDelay() {
- Handler handler = getHandler();
- handler.removeMessages(MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT);
- handler.sendEmptyMessageDelayed(MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT,
- DELAY_AUTOSELECT_FIRST_FOUND_CONTACT_MILLIS);
- }
-
- /**
- * Selects the first contact in the list in search mode.
- */
- protected void selectFirstFoundContact() {
- if (!mSearchMode) {
- return;
- }
-
- Uri selectedUri = null;
- String queryString = mListFragment.getQueryString();
- if (queryString != null
- && queryString.length() >= AUTOSELECT_FIRST_FOUND_CONTACT_MIN_QUERY_LENGTH) {
- selectedUri = mListFragment.getFirstContactUri();
- }
-
- mListFragment.setSelectedContactUri(selectedUri);
- mListFragment.eraseSelectedUri(mPrefs);
- mListFragment.requestSelectionOnScreen(true);
- if (mContactContentDisplayed) {
- setupContactDetailFragment(selectedUri);
- }
- }
-
@Override
public void onContactListFilterCustomizationRequest() {
startActivityForResult(new Intent(this, CustomContactListFilterActivity.class),
@@ -528,15 +366,7 @@
}
private void setupContactDetailFragment(final Uri contactLookupUri) {
- if (mDetailFragment == null) {
- mDetailFragment = new ContactDetailFragment();
- mDetailFragment.loadUri(contactLookupUri);
- getFragmentManager().openTransaction()
- .replace(R.id.detail_container, mDetailFragment)
- .commit();
- } else {
- mDetailFragment.loadUri(contactLookupUri);
- }
+ mDetailFragment.loadUri(contactLookupUri);
}
/**
@@ -571,6 +401,10 @@
fragment.setSelectionVisible(mContactContentDisplayed);
fragment.setQuickContactEnabled(!mContactContentDisplayed);
fragment.setFilterEnabled(!mRequest.isSearchMode());
+ fragment.setPersistentSelectionEnabled(!mRequest.isSearchMode());
+ if (mContactListFilterController.isLoaded()) {
+ fragment.setFilter(mContactListFilterController.getFilter());
+ }
return fragment;
}
@@ -680,13 +514,17 @@
}
private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
+
+ @Override
+ public void onSelectionChange() {
+ if (mContactContentDisplayed) {
+ setupContactDetailFragment(mListFragment.getSelectedContactUri());
+ }
+ }
+
@Override
public void onViewContactAction(Uri contactLookupUri) {
if (mContactContentDisplayed) {
- resetContactSelectionInIntent();
-
- mListFragment.setSelectedContactUri(contactLookupUri);
- mListFragment.saveSelectedUri(mPrefs);
setupContactDetailFragment(contactLookupUri);
} else {
startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri));
@@ -749,16 +587,17 @@
@Override
public void onInvalidSelection() {
- showDefaultSelection();
+ ContactListFilter filter =
+ new ContactListFilter(ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
+ mContactListFilterController.setContactListFilter(filter, true);
+ mListFragment.setFilter(filter);
}
}
private class DetailFragmentListener implements ContactDetailFragment.Listener {
@Override
public void onContactNotFound() {
- resetContactSelectionInIntent();
- setupContactDetailFragment(null);
- showDefaultSelection();
+ // Nothing needs to be done here
}
@Override
@@ -891,9 +730,8 @@
}
boolean groupActionsEnabled = false;
- if (mListFragment instanceof DefaultContactBrowseListFragment) {
- ContactListFilter filter =
- ((DefaultContactBrowseListFragment)mListFragment).getFilter();
+ if (mListFragment != null) {
+ ContactListFilter filter = mListFragment.getFilter();
if (filter != null
&& filter.filterType == ContactListFilter.FILTER_TYPE_GROUP
&& !filter.groupReadOnly) {
@@ -944,15 +782,13 @@
return true;
}
case R.id.menu_rename_group: {
- ContactListFilter filter =
- ((DefaultContactBrowseListFragment)mListFragment).getFilter();
+ ContactListFilter filter = mListFragment.getFilter();
GroupRenamingDialogFragment.show(getFragmentManager(), filter.groupId,
filter.title);
return true;
}
case R.id.menu_delete_group: {
- ContactListFilter filter =
- ((DefaultContactBrowseListFragment)mListFragment).getFilter();
+ ContactListFilter filter = mListFragment.getFilter();
GroupDeletionDialogFragment.show(getFragmentManager(), filter.groupId,
filter.title);
return true;
@@ -1045,24 +881,12 @@
}
break;
}
- case SUBACTIVITY_EDIT_CONTACT: {
- mListFragment.requestSelectionOnScreen(true);
- break;
- }
+ case SUBACTIVITY_EDIT_CONTACT:
case SUBACTIVITY_NEW_CONTACT: {
- if (resultCode == RESULT_OK && mContactContentDisplayed) {
- resetContactSelectionInIntent();
-
- final Uri newContactUri = data.getData();
- if (mContactContentDisplayed) {
- setupContactDetailFragment(newContactUri);
- }
-
+ if (resultCode == RESULT_OK) {
mRequest.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
- mListFragment.setSelectedContactUri(newContactUri);
- mListFragment.saveSelectedUri(mPrefs);
- mListFragment.requestSelectionOnScreen(true);
+ mListFragment.setSelectedContactUri(data.getData());
}
break;
}
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index 197dc51..a1c7c3f 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -18,13 +18,18 @@
import com.android.contacts.R;
import com.android.contacts.widget.ListViewUtils;
+import android.app.Activity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
@@ -40,19 +45,50 @@
private static final String KEY_SELECTED_URI = "selectedUri";
private static final String KEY_SELECTION_VERIFIED = "selectionVerified";
+ private static final String KEY_FILTER_ENABLED = "filterEnabled";
+
+ private static final String KEY_PERSISTENT_SELECTION_ENABLED = "persistenSelectionEnabled";
+ private static final String PERSISTENT_SELECTION_PREFIX = "defaultContactBrowserSelection";
+
+ /**
+ * The id for a delayed message that triggers automatic selection of the first
+ * found contact in search mode.
+ */
+ private static final int MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT = 1;
+
+ /**
+ * The delay that is used for automatically selecting the first found contact.
+ */
+ private static final int DELAY_AUTOSELECT_FIRST_FOUND_CONTACT_MILLIS = 500;
+
+ /**
+ * The minimum number of characters in the search query that is required
+ * before we automatically select the first found contact.
+ */
+ private static final int AUTOSELECT_FIRST_FOUND_CONTACT_MIN_QUERY_LENGTH = 2;
+
+ private static final int MESSAGE_REQUEST_SELECTION_TO_SCREEN = 2;
private static final int SELECTED_ID_LOADER = -3;
+ private static final String ARG_CONTACT_URI = "uri";
- private static final int SELECTION_VISIBILITY_REQUEST_NONE = 0;
- private static final int SELECTION_VISIBILITY_REQUEST_SMOOTH = 1;
- private static final int SELECTION_VISIBILITY_REQUEST_INSTANT = 2;
+ private SharedPreferences mPrefs;
+ private Handler mHandler;
+ private boolean mStartedLoading;
+ private boolean mSelectionRequired;
+ private boolean mSelectionToScreenRequested;
+ private boolean mSmoothScrollRequested;
+ private boolean mSelectionPersistenceRequested;
private Uri mSelectedContactUri;
private long mSelectedContactDirectoryId;
private String mSelectedContactLookupKey;
- private int mSelectionVisibilityRequest;
private boolean mSelectionVerified;
private boolean mLoadingLookupKey;
+ private boolean mFilterEnabled;
+ private ContactListFilter mFilter;
+ private boolean mPersistentSelectionEnabled;
+ private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX;
protected OnContactBrowserActionListener mListener;
@@ -60,30 +96,79 @@
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- return new CursorLoader(getContext(),
- mSelectedContactUri,
- new String[] { Contacts.LOOKUP_KEY },
- null,
- null,
- null);
+ Uri contactUri = args.getParcelable(ARG_CONTACT_URI);
+ return new CursorLoader(getContext(), contactUri, new String[] { Contacts.LOOKUP_KEY },
+ null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- mLoadingLookupKey = false;
String lookupKey = null;
if (data != null) {
if (data.moveToFirst()) {
lookupKey = data.getString(0);
}
}
- if (!TextUtils.equals(mSelectedContactLookupKey, lookupKey)) {
- mSelectedContactLookupKey = lookupKey;
- configureContactSelection();
- }
+ onLookupKeyLoadFinished(lookupKey);
}
};
+ private Handler getHandler() {
+ if (mHandler == null) {
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT:
+ selectDefaultContact();
+ break;
+ case MESSAGE_REQUEST_SELECTION_TO_SCREEN:
+ requestSelectionToScreen();
+ break;
+ }
+ }
+ };
+ }
+ return mHandler;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
+ restoreSelectedUri();
+ }
+
+ public void setPersistentSelectionEnabled(boolean flag) {
+ this.mPersistentSelectionEnabled = flag;
+ }
+
+ public void setFilter(ContactListFilter filter) {
+ if (mFilter == null && filter == null) {
+ return;
+ }
+
+ if (mFilter != null && mFilter.equals(filter)) {
+ return;
+ }
+
+ mFilter = filter;
+ restoreSelectedUri();
+ reloadData();
+ }
+
+ public ContactListFilter getFilter() {
+ return mFilter;
+ }
+
+ public boolean isFilterEnabled() {
+ return mFilterEnabled;
+ }
+
+ public void setFilterEnabled(boolean flag) {
+ this.mFilterEnabled = flag;
+ }
+
@Override
public void restoreSavedState(Bundle savedState) {
super.restoreSavedState(savedState);
@@ -92,6 +177,8 @@
return;
}
+ mPersistentSelectionEnabled = savedState.getBoolean(KEY_PERSISTENT_SELECTION_ENABLED);
+ mFilterEnabled = savedState.getBoolean(KEY_FILTER_ENABLED);
mSelectedContactUri = savedState.getParcelable(KEY_SELECTED_URI);
mSelectionVerified = savedState.getBoolean(KEY_SELECTION_VERIFIED);
parseSelectedContactUri();
@@ -100,6 +187,7 @@
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_FILTER_ENABLED, mFilterEnabled);
outState.putParcelable(KEY_SELECTED_URI, mSelectedContactUri);
outState.putBoolean(KEY_SELECTION_VERIFIED, mSelectionVerified);
}
@@ -112,14 +200,36 @@
}
protected void startLoadingContactLookupKey() {
- if (isSelectionVisible() && mSelectedContactUri != null &&
- (mSelectedContactDirectoryId == Directory.DEFAULT ||
- mSelectedContactDirectoryId == Directory.LOCAL_INVISIBLE)) {
- mLoadingLookupKey = true;
- getLoaderManager().restartLoader(SELECTED_ID_LOADER, null, mIdLoaderCallbacks);
- } else {
- getLoaderManager().stopLoader(SELECTED_ID_LOADER);
+ getLoaderManager().stopLoader(SELECTED_ID_LOADER);
+
+ if (!isSelectionVisible()) {
+ return;
}
+
+ mLoadingLookupKey = true;
+
+ if (mSelectedContactUri == null) {
+ onLookupKeyLoadFinished(null);
+ return;
+ }
+
+ if (mSelectedContactDirectoryId != Directory.DEFAULT
+ && mSelectedContactDirectoryId != Directory.LOCAL_INVISIBLE) {
+ onLookupKeyLoadFinished(mSelectedContactLookupKey);
+ } else {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(ARG_CONTACT_URI, mSelectedContactUri);
+ getLoaderManager().restartLoader(SELECTED_ID_LOADER, bundle, mIdLoaderCallbacks);
+ }
+ }
+
+ protected void onLookupKeyLoadFinished(String lookupKey) {
+ mLoadingLookupKey = false;
+ if (!TextUtils.equals(mSelectedContactLookupKey, lookupKey)) {
+ mSelectedContactLookupKey = lookupKey;
+ getAdapter().setSelectedContact(mSelectedContactDirectoryId, mSelectedContactLookupKey);
+ }
+ checkSelection();
}
@Override
@@ -145,17 +255,31 @@
return mSelectedContactUri;
}
+ /**
+ * Sets the new selection for the list.
+ */
public void setSelectedContactUri(Uri uri) {
+ setSelectedContactUri(uri, true, true, true);
+ }
+
+ private void setSelectedContactUri(
+ Uri uri, boolean required, boolean smoothScroll, boolean persistent) {
+ mSmoothScrollRequested = smoothScroll;
+ mSelectionToScreenRequested = true;
+
if ((mSelectedContactUri == null && uri != null)
|| (mSelectedContactUri != null && !mSelectedContactUri.equals(uri))) {
+ mSelectionVerified = false;
+ mSelectionRequired = required;
+ mSelectionPersistenceRequested = persistent;
mSelectedContactUri = uri;
-
parseSelectedContactUri();
- if (isAdded()) {
+ if (mStartedLoading) {
// Configure the adapter to show the selection based on the lookup key extracted
// from the URI
- configureAdapter();
+ getAdapter().setSelectedContact(
+ mSelectedContactDirectoryId, mSelectedContactLookupKey);
// Also, launch a loader to pick up a new lookup key in case it has changed
startLoadingContactLookupKey();
@@ -187,27 +311,24 @@
@Override
protected void configureAdapter() {
super.configureAdapter();
- configureContactSelection();
- }
- /**
- * Configures the adapter with the identity of the currently selected contact.
- */
- private void configureContactSelection() {
ContactListAdapter adapter = getAdapter();
if (adapter == null) {
return;
}
+ if (mFilterEnabled && mFilter != null) {
+ adapter.setFilter(mFilter);
+ }
+
adapter.setSelectedContact(mSelectedContactDirectoryId, mSelectedContactLookupKey);
- checkSelection();
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
super.onLoadFinished(loader, data);
+ mSelectionVerified = false;
checkSelection();
- requestSelectionOnScreenIfNeeded();
}
private void checkSelection() {
@@ -220,10 +341,77 @@
}
ContactListAdapter adapter = getAdapter();
- if (adapter.hasValidSelection()) {
- mSelectionVerified = true;
- } else {
+
+ int selectedPosition = adapter.getSelectedContactPosition();
+ if (mSelectionRequired && selectedPosition == -1) {
notifyInvalidSelection();
+ return;
+ }
+
+ if (selectedPosition == -1) {
+ saveSelectedUri(null);
+
+ if (isSearchMode()) {
+ selectFirstFoundContactAfterDelay();
+ } else {
+ selectDefaultContact();
+ }
+
+ if (mSelectedContactUri != null) {
+ // The default selection is now loading and this method will be called again
+ return;
+ }
+ }
+
+ mSelectionRequired = false;
+ mSelectionVerified = true;
+
+ if (mSelectionPersistenceRequested) {
+ saveSelectedUri(mSelectedContactUri);
+ mSelectionPersistenceRequested = false;
+ }
+
+ if (mSelectionToScreenRequested) {
+ getHandler().removeMessages(MESSAGE_REQUEST_SELECTION_TO_SCREEN);
+ getHandler().sendEmptyMessage(MESSAGE_REQUEST_SELECTION_TO_SCREEN);
+ }
+
+ if (mListener != null) {
+ mListener.onSelectionChange();
+ }
+ }
+
+ /**
+ * Automatically selects the first found contact in search mode. The selection
+ * is updated after a delay to allow the user to type without to much UI churn
+ * and to save bandwidth on directory queries.
+ */
+ public void selectFirstFoundContactAfterDelay() {
+ Handler handler = getHandler();
+ handler.removeMessages(MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT);
+
+ String queryString = getQueryString();
+ if (queryString != null
+ && queryString.length() >= AUTOSELECT_FIRST_FOUND_CONTACT_MIN_QUERY_LENGTH) {
+ handler.sendEmptyMessageDelayed(MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT,
+ DELAY_AUTOSELECT_FIRST_FOUND_CONTACT_MILLIS);
+ } else {
+ setSelectedContactUri(null, false, false, false);
+ }
+ }
+
+ protected void selectDefaultContact() {
+ Uri firstContactUri = getAdapter().getFirstContactUri();
+ setSelectedContactUri(firstContactUri, false, true, false);
+ }
+
+ protected void requestSelectionToScreen() {
+ int selectedPosition = getAdapter().getSelectedContactPosition();
+ if (selectedPosition != -1) {
+ ListView listView = getListView();
+ ListViewUtils.requestPositionToScreen(listView,
+ selectedPosition + listView.getHeaderViewsCount(), mSmoothScrollRequested);
+ mSelectionToScreenRequested = false;
}
}
@@ -232,21 +420,21 @@
return mLoadingLookupKey || super.isLoading();
}
- public Uri getFirstContactUri() {
- ContactListAdapter adapter = getAdapter();
- return adapter.getFirstContactUri();
- }
-
@Override
public void startLoading() {
- mSelectionVerified = false;
- super.startLoading();
+ if (!mFilterEnabled || mFilter != null) {
+ mStartedLoading = true;
+ mSelectionVerified = false;
+ super.startLoading();
+ }
}
@Override
public void reloadData() {
- mSelectionVerified = false;
- super.reloadData();
+ if (mStartedLoading) {
+ mSelectionVerified = false;
+ super.reloadData();
+ }
}
public void setOnContactListActionListener(OnContactBrowserActionListener listener) {
@@ -258,7 +446,8 @@
}
public void viewContact(Uri contactUri) {
- if (mListener != null) mListener.onViewContactAction(contactUri);
+ setSelectedContactUri(contactUri, false, false, true);
+ if (mListener != null) { mListener.onViewContactAction(contactUri); }
}
public void editContact(Uri contactUri) {
@@ -295,45 +484,38 @@
if (mListener != null) mListener.onFinishAction();
}
- public void requestSelectionOnScreen(boolean smooth) {
- mSelectionVisibilityRequest = smooth
- ? SELECTION_VISIBILITY_REQUEST_SMOOTH
- : SELECTION_VISIBILITY_REQUEST_INSTANT;
- requestSelectionOnScreenIfNeeded();
- }
-
- @Override
- protected void completeRestoreInstanceState() {
- super.completeRestoreInstanceState();
- requestSelectionOnScreenIfNeeded();
- }
-
- private void requestSelectionOnScreenIfNeeded() {
- if (mSelectionVisibilityRequest == SELECTION_VISIBILITY_REQUEST_NONE) {
+ private void saveSelectedUri(Uri contactUri) {
+ if (!mPersistentSelectionEnabled) {
return;
}
- ContactListAdapter adapter = getAdapter();
- if (adapter == null || adapter.isLoading()) {
+ Editor editor = mPrefs.edit();
+ if (contactUri == null) {
+ editor.remove(getPersistentSelectionKey());
+ } else {
+ editor.putString(getPersistentSelectionKey(), contactUri.toString());
+ }
+ editor.apply();
+ }
+
+ private void restoreSelectedUri() {
+ if (!mPersistentSelectionEnabled || mPrefs == null || mSelectionRequired) {
return;
}
- int position = adapter.getSelectedContactPosition();
- if (position != -1) {
- boolean smooth = mSelectionVisibilityRequest == SELECTION_VISIBILITY_REQUEST_SMOOTH;
- mSelectionVisibilityRequest = SELECTION_VISIBILITY_REQUEST_NONE;
- ListView listView = getListView();
- ListViewUtils.requestPositionToScreen(
- listView, position + listView.getHeaderViewsCount(), smooth);
+ String selectedUri = mPrefs.getString(getPersistentSelectionKey(), null);
+ if (selectedUri == null) {
+ setSelectedContactUri(null, false, false, false);
+ } else {
+ setSelectedContactUri(Uri.parse(selectedUri), false, false, false);
}
}
- public void saveSelectedUri(SharedPreferences preferences) {
- }
-
- public void restoreSelectedUri(SharedPreferences preferences) {
- }
-
- public void eraseSelectedUri(SharedPreferences preferences) {
+ private String getPersistentSelectionKey() {
+ if (mFilter == null) {
+ return mPersistentSelectionPrefix;
+ } else {
+ return mPersistentSelectionPrefix + "-" + mFilter.getId();
+ }
}
}
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index 7b5641b..f0b4a1d 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -872,10 +872,6 @@
}
}
- private View findViewById(int id) {
- return mView.findViewById(id);
- }
-
// TODO: fix PluralRules to handle zero correctly and use Resources.getQuantityText directly
public String getQuantityText(int count, int zeroResourceId, int pluralResourceId) {
if (count == 0) {
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index cc1cdb0..afe29df 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -141,6 +141,8 @@
} else if (Intent.ACTION_VIEW.equals(action)) {
request.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
request.setContactUri(intent.getData());
+ intent.setAction(Intent.ACTION_DEFAULT);
+ intent.setData(null);
} else if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
// When we get a FILTER_CONTACTS_ACTION, it represents search in the context
// of some other action. Let's retrieve the original action to provide proper
@@ -157,10 +159,6 @@
}
}
- if (request == null) {
- request = new ContactsRequest();
- }
-
request.setSearchMode(true);
// Since this is the filter activity it receives all intents
@@ -176,6 +174,8 @@
} else {
request.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
request.setContactUri(data);
+ intent.setAction(Intent.ACTION_DEFAULT);
+ intent.setData(null);
}
} else if (Intents.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED.equals(action)) {
request.setRedirectIntent(new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData()));
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index e1100f6..3084a66 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -17,10 +17,7 @@
import com.android.contacts.R;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
import android.database.Cursor;
-import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -36,36 +33,19 @@
*/
public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
- private static final String KEY_FILTER_ENABLED = "filterEnabled";
-
- private static final String PERSISTENT_SELECTION_PREFIX = "defaultContactBrowserSelection";
- private static final String KEY_SEARCH_MODE_CONTACT_URI_SUFFIX = "search";
-
private View mCounterHeaderView;
private View mSearchHeaderView;
- private boolean mFilterEnabled;
- private ContactListFilter mFilter;
- private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX;
-
public DefaultContactBrowseListFragment() {
setPhotoLoaderEnabled(true);
setSectionHeaderDisplayEnabled(true);
setAizyEnabled(true);
}
- public void setFilter(ContactListFilter filter) {
- mFilter = filter;
- }
-
- public ContactListFilter getFilter() {
- return mFilter;
- }
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putBoolean(KEY_FILTER_ENABLED, mFilterEnabled);
}
@Override
@@ -76,7 +56,6 @@
return;
}
- setFilterEnabled(savedState.getBoolean(KEY_FILTER_ENABLED));
}
@Override
@@ -93,16 +72,6 @@
}
@Override
- protected void configureAdapter() {
- super.configureAdapter();
-
- DefaultContactListAdapter adapter = (DefaultContactListAdapter)getAdapter();
- if (adapter != null && mFilter != null) {
- adapter.setFilter(mFilter);
- }
- }
-
- @Override
protected View inflateView(LayoutInflater inflater, ViewGroup container) {
return inflater.inflate(R.layout.contacts_list_content, null);
}
@@ -177,58 +146,4 @@
}
}
}
-
- public boolean isFilterEnabled() {
- return mFilterEnabled;
- }
-
- public void setFilterEnabled(boolean flag) {
- this.mFilterEnabled = flag;
- }
-
- @Override
- public void startLoading() {
- if (!mFilterEnabled || mFilter != null) {
- super.startLoading();
- }
- }
-
- @Override
- public void saveSelectedUri(SharedPreferences preferences) {
- Uri uri = getSelectedContactUri();
- if (uri == null) {
- eraseSelectedUri(preferences);
- } else {
- Editor editor = preferences.edit();
- editor.putString(getPersistentSelectionKey(), uri.toString());
- editor.apply();
- }
- }
-
- @Override
- public void eraseSelectedUri(SharedPreferences preferences) {
- Editor editor = preferences.edit();
- editor.remove(getPersistentSelectionKey());
- editor.apply();
- }
-
- @Override
- public void restoreSelectedUri(SharedPreferences preferences) {
- String selectedUri = preferences.getString(getPersistentSelectionKey(), null);
- if (selectedUri == null) {
- setSelectedContactUri(null);
- } else {
- setSelectedContactUri(Uri.parse(selectedUri));
- }
- }
-
- private String getPersistentSelectionKey() {
- if (isSearchMode()) {
- return mPersistentSelectionPrefix + "-" + KEY_SEARCH_MODE_CONTACT_URI_SUFFIX;
- } else if (mFilter == null) {
- return mPersistentSelectionPrefix;
- } else {
- return mPersistentSelectionPrefix + "-" + mFilter.getId();
- }
- }
}
diff --git a/src/com/android/contacts/list/OnContactBrowserActionListener.java b/src/com/android/contacts/list/OnContactBrowserActionListener.java
index 80d4838..771f251 100644
--- a/src/com/android/contacts/list/OnContactBrowserActionListener.java
+++ b/src/com/android/contacts/list/OnContactBrowserActionListener.java
@@ -23,6 +23,12 @@
public interface OnContactBrowserActionListener {
/**
+ * Notification of selection change, invoked when the selection of activated
+ * item(s) is change by either a user action or some other event, e.g. sync.
+ */
+ void onSelectionChange();
+
+ /**
* Opens the specified contact for viewing.
*
* @param contactLookupUri The lookup-uri of the Contact that should be opened
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index dacc9cb..eb5c65c 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -238,6 +238,7 @@
}
});
+ mView.setVisibility(View.INVISIBLE);
return mView;
}