Merge "Fix broken behavior around ImportVCardActivity."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 037af20..da4856c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -260,6 +260,9 @@
For example, this may be used to set a phone number's label to "Vaction house" -->
<string name="customLabelPickerTitle">Custom label name</string>
+ <!-- The menu item to open the list of groups to display -->
+ <string name="menu_displayGroup">Display options</string>
+
<!-- Check box label that allows calls to the contact to be sent directly to voicemail -->
<string name="send_to_voicemail_checkbox">Send calls directly to voicemail</string>
@@ -1358,6 +1361,9 @@
<!-- Contact list filter selection indicating that the list shows all contacts with phone numbers [CHAR LIMIT=64] -->
<string name="list_filter_phones">Contacts with phone numbers</string>
+ <!-- Contact list filter selection indicating that the list shows only the selected contact [CHAR LIMIT=64] -->
+ <string name="list_filter_single">Contact</string>
+
<!-- Title of the activity that allows the user to customize filtering of contact list [CHAR LIMIT=128] -->
<string name="custom_list_filter">Define custom view</string>
diff --git a/src/com/android/contacts/activities/ContactBrowserActivity.java b/src/com/android/contacts/activities/ContactBrowserActivity.java
index ce484f0..054c50f 100644
--- a/src/com/android/contacts/activities/ContactBrowserActivity.java
+++ b/src/com/android/contacts/activities/ContactBrowserActivity.java
@@ -27,6 +27,7 @@
import com.android.contacts.list.ContactListFilterController;
import com.android.contacts.list.ContactsIntentResolver;
import com.android.contacts.list.ContactsRequest;
+import com.android.contacts.list.CustomContactListFilterActivity;
import com.android.contacts.list.DefaultContactBrowseListFragment;
import com.android.contacts.list.DirectoryListLoader;
import com.android.contacts.list.OnContactBrowserActionListener;
@@ -48,7 +49,6 @@
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -57,7 +57,6 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -80,15 +79,15 @@
*/
public class ContactBrowserActivity extends Activity
implements View.OnCreateContextMenuListener, ActionBarAdapter.Listener,
- DialogManager.DialogShowingViewActivity {
+ DialogManager.DialogShowingViewActivity,
+ ContactListFilterController.ContactListFilterListener {
private static final String TAG = "ContactBrowserActivity";
private static final int SUBACTIVITY_NEW_CONTACT = 2;
private static final int SUBACTIVITY_SETTINGS = 3;
private static final int SUBACTIVITY_EDIT_CONTACT = 4;
-
- private static final String KEY_DEFAULT_CONTACT_URI = "defaultSelectedContactUri";
+ private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 5;
private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20;
@@ -129,6 +128,7 @@
public ContactBrowserActivity() {
mIntentResolver = new ContactsIntentResolver(this);
mContactListFilterController = new ContactListFilterController(this);
+ mContactListFilterController.addListener(this);
}
@Override
@@ -136,9 +136,11 @@
if (fragment instanceof ContactBrowseListFragment) {
mListFragment = (ContactBrowseListFragment)fragment;
mListFragment.setOnContactListActionListener(new ContactBrowserActionListener());
- if (mListFragment instanceof DefaultContactBrowseListFragment) {
- ((DefaultContactBrowseListFragment) mListFragment).setContactListFilterController(
- mContactListFilterController);
+ if (mListFragment instanceof DefaultContactBrowseListFragment
+ && mContactListFilterController != null
+ && mContactListFilterController.isLoaded()) {
+ ((DefaultContactBrowseListFragment) mListFragment).setFilter(
+ mContactListFilterController.getFilter());
}
} else if (fragment instanceof ContactNoneFragment) {
mEmptyFragment = (ContactNoneFragment)fragment;
@@ -216,7 +218,9 @@
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
- Uri uri = intent.getData();
+ mRequest = mIntentResolver.resolveIntent(getIntent());
+
+ Uri uri = mRequest.getContactUri();
if (uri == null) {
return;
}
@@ -227,27 +231,20 @@
mActionBarAdapter.setSearchMode(false);
}
}
- setSelectedContactUri(uri);
- setupContactDetailFragment(uri);
+ mListFragment.setSelectedContactUri(uri);
mListFragment.requestSelectionOnScreen(true);
+ if (mContactContentDisplayed) {
+ setupContactDetailFragment(uri);
+ }
}
}
- public void setSelectedContactUri(Uri contactLookupUri) {
- mListFragment.setSelectedContactUri(contactLookupUri);
-
- Editor editor = mPrefs.edit();
- if (contactLookupUri == null) {
- editor.remove(KEY_DEFAULT_CONTACT_URI);
- } else {
- editor.putString(KEY_DEFAULT_CONTACT_URI, contactLookupUri.toString());
+ @Override
+ protected void onStart() {
+ if (mContactListFilterController != null) {
+ mContactListFilterController.startLoading();
}
- editor.apply();
- }
-
- public Uri getDefaultSelectedContactUri() {
- String uriString = mPrefs.getString(KEY_DEFAULT_CONTACT_URI, null);
- return TextUtils.isEmpty(uriString) ? null : Uri.parse(uriString);
+ super.onStart();
}
private void configureListFragment(boolean fromRequest) {
@@ -315,23 +312,14 @@
}
}
- Uri selectUri = null;
if (fromRequest) {
- selectUri = mRequest.getContactUri();
+ Uri selectUri = mRequest.getContactUri();
if (selectUri != null) {
- setSelectedContactUri(selectUri);
+ mListFragment.setSelectedContactUri(selectUri);
+ mListFragment.requestSelectionOnScreen(false);
}
}
- if (selectUri == null && mListFragment.getSelectedContactUri() == null) {
- selectUri = getDefaultSelectedContactUri();
- }
-
- if (selectUri != null) {
- mListFragment.setSelectedContactUri(selectUri);
- mListFragment.requestSelectionOnScreen(false);
- }
-
if (replaceList) {
getFragmentManager().openTransaction()
.replace(R.id.list_container, mListFragment)
@@ -357,6 +345,48 @@
}
}
+ @Override
+ public void onContactListFiltersLoaded() {
+ if (mListFragment instanceof DefaultContactBrowseListFragment) {
+ DefaultContactBrowseListFragment fragment =
+ (DefaultContactBrowseListFragment) mListFragment;
+ restoreListSelection(fragment);
+
+ // Filters have been loaded - now we can start loading the list itself
+ fragment.startLoading();
+ }
+ }
+
+ @Override
+ public void onContactListFilterChanged() {
+ // If there was a request to show a specific contact, that's no longer the case
+ // because the user has explicitly changed the filter.
+ mRequest.setContactUri(null);
+
+ if (mListFragment instanceof DefaultContactBrowseListFragment) {
+ DefaultContactBrowseListFragment fragment =
+ (DefaultContactBrowseListFragment) mListFragment;
+ restoreListSelection(fragment);
+
+ fragment.reloadData();
+ }
+ }
+
+ private void restoreListSelection(DefaultContactBrowseListFragment fragment) {
+ fragment.setFilter(mContactListFilterController.getFilter());
+ fragment.restoreSelectedUri(mPrefs);
+ fragment.requestSelectionOnScreen(false);
+ if (mContactContentDisplayed) {
+ setupContactDetailFragment(fragment.getSelectedContactUri());
+ }
+ }
+
+ @Override
+ public void onContactListFilterCustomizationRequest() {
+ startActivityForResult(new Intent(this, CustomContactListFilterActivity.class),
+ SUBACTIVITY_CUSTOMIZE_FILTER);
+ }
+
private void setupContactDetailFragment(final Uri contactLookupUri) {
if (mDetailFragment != null && contactLookupUri != null
&& contactLookupUri.equals(mDetailFragment.getUri())) {
@@ -508,7 +538,8 @@
@Override
public void onViewContactAction(Uri contactLookupUri) {
if (mContactContentDisplayed) {
- setSelectedContactUri(contactLookupUri);
+ mListFragment.setSelectedContactUri(contactLookupUri);
+ mListFragment.saveSelectedUri(mPrefs);
setupContactDetailFragment(contactLookupUri);
} else {
startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri));
@@ -568,6 +599,37 @@
public void onFinishAction() {
onBackPressed();
}
+
+ @Override
+ public void onInvalidSelection() {
+ 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 uncoditionally 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.requestSelectionOnScreen(false);
+ }
+ }
+ if (mContactContentDisplayed) {
+ setupContactDetailFragment(requestedContactUri);
+ }
+ }
}
private class DetailFragmentListener implements ContactDetailFragment.Listener {
@@ -768,6 +830,12 @@
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
+ case SUBACTIVITY_CUSTOMIZE_FILTER: {
+ if (resultCode == Activity.RESULT_OK) {
+ mContactListFilterController.selectCustomFilter();
+ }
+ break;
+ }
case SUBACTIVITY_EDIT_CONTACT: {
mListFragment.requestSelectionOnScreen(true);
break;
@@ -776,8 +844,15 @@
case SUBACTIVITY_NEW_CONTACT: {
if (resultCode == RESULT_OK && mContactContentDisplayed) {
final Uri newContactUri = data.getData();
- setSelectedContactUri(newContactUri);
- setupContactDetailFragment(newContactUri);
+ if (mContactContentDisplayed) {
+ setupContactDetailFragment(newContactUri);
+ }
+
+ mRequest.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
+ mRequest.setContactUri(newContactUri);
+ mListFragment.setSelectedContactUri(newContactUri);
+ mListFragment.saveSelectedUri(mPrefs);
+ mListFragment.requestSelectionOnScreen(true);
}
break;
}
diff --git a/src/com/android/contacts/activities/ContactSearchActivity.java b/src/com/android/contacts/activities/ContactSearchActivity.java
index 0c8d141..615f182 100644
--- a/src/com/android/contacts/activities/ContactSearchActivity.java
+++ b/src/com/android/contacts/activities/ContactSearchActivity.java
@@ -159,6 +159,10 @@
public void onFinishAction() {
onBackPressed();
}
+
+ @Override
+ public void onInvalidSelection() {
+ }
}
private PhoneNumberInteraction getPhoneNumberCallInteraction() {
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index cfe9710..290358a 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -21,9 +21,7 @@
import com.android.contacts.list.ContactPickerFragment;
import com.android.contacts.list.ContactsIntentResolver;
import com.android.contacts.list.ContactsRequest;
-import com.android.contacts.list.DefaultContactBrowseListFragment;
import com.android.contacts.list.DirectoryListLoader;
-import com.android.contacts.list.OnContactBrowserActionListener;
import com.android.contacts.list.OnContactPickerActionListener;
import com.android.contacts.list.OnPhoneNumberPickerActionListener;
import com.android.contacts.list.OnPostalAddressPickerActionListener;
@@ -59,8 +57,6 @@
private int mActionCode = -1;
- private boolean mSearchInitiated;
-
private ContactsRequest mRequest;
private SearchView mSearchView;
@@ -255,10 +251,7 @@
}
public void setupActionListener() {
- if (mListFragment instanceof DefaultContactBrowseListFragment) {
- ((DefaultContactBrowseListFragment) mListFragment).setOnContactListActionListener(
- new ContactBrowserActionListener());
- } else if (mListFragment instanceof ContactPickerFragment) {
+ if (mListFragment instanceof ContactPickerFragment) {
((ContactPickerFragment) mListFragment).setOnContactPickerActionListener(
new ContactPickerActionListener());
} else if (mListFragment instanceof PhoneNumberPickerFragment) {
@@ -272,63 +265,6 @@
}
}
- private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
- @Override
- public void onViewContactAction(Uri contactLookupUri) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void onCreateNewContactAction() {
- Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
- Bundle extras = getIntent().getExtras();
- if (extras != null) {
- intent.putExtras(extras);
- }
- startActivity(intent);
- }
-
- @Override
- public void onEditContactAction(Uri contactLookupUri) {
- Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
- Bundle extras = getIntent().getExtras();
- if (extras != null) {
- intent.putExtras(extras);
- }
- startActivity(intent);
- }
-
- @Override
- public void onAddToFavoritesAction(Uri contactUri) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void onRemoveFromFavoritesAction(Uri contactUri) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void onCallContactAction(Uri contactUri) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void onSmsContactAction(Uri contactUri) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void onDeleteContactAction(Uri contactUri) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void onFinishAction() {
- onBackPressed();
- }
- }
-
private final class ContactPickerActionListener implements OnContactPickerActionListener {
@Override
public void onCreateNewContactAction() {
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index f99134b..5a81f6a 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -21,6 +21,7 @@
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
+import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -38,6 +39,7 @@
ContactEntryListFragment<ContactListAdapter> {
private static final String KEY_SELECTED_URI = "selectedUri";
+ private static final String KEY_SELECTION_VERIFIED = "selectionVerified";
private static final int SELECTED_ID_LOADER = -3;
@@ -49,8 +51,10 @@
private long mSelectedContactDirectoryId;
private String mSelectedContactLookupKey;
private int mSelectionVisibilityRequest;
+ private boolean mSelectionVerified;
+ private boolean mLoadingLookupKey;
- private OnContactBrowserActionListener mListener;
+ protected OnContactBrowserActionListener mListener;
private LoaderCallbacks<Cursor> mIdLoaderCallbacks = new LoaderCallbacks<Cursor>() {
@@ -66,6 +70,7 @@
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ mLoadingLookupKey = false;
String lookupKey = null;
if (data != null) {
if (data.moveToFirst()) {
@@ -76,7 +81,6 @@
mSelectedContactLookupKey = lookupKey;
configureContactSelection();
}
- return;
}
};
@@ -89,6 +93,7 @@
}
mSelectedContactUri = savedState.getParcelable(KEY_SELECTED_URI);
+ mSelectionVerified = savedState.getBoolean(KEY_SELECTION_VERIFIED);
parseSelectedContactUri();
}
@@ -96,6 +101,7 @@
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(KEY_SELECTED_URI, mSelectedContactUri);
+ outState.putBoolean(KEY_SELECTION_VERIFIED, mSelectionVerified);
}
@Override
@@ -109,6 +115,7 @@
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);
@@ -165,7 +172,7 @@
}
String directoryParam =
- mSelectedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
+ mSelectedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
mSelectedContactDirectoryId = TextUtils.isEmpty(directoryParam)
? Directory.DEFAULT
: Long.parseLong(directoryParam);
@@ -193,6 +200,49 @@
}
adapter.setSelectedContact(mSelectedContactDirectoryId, mSelectedContactLookupKey);
+ checkSelection();
+ }
+
+ @Override
+ protected void onPartitionLoaded(int partitionIndex, Cursor data) {
+ super.onPartitionLoaded(partitionIndex, data);
+ checkSelection();
+ }
+
+ private void checkSelection() {
+ if (mSelectionVerified || isSearchMode()) {
+ return;
+ }
+
+ ContactListAdapter adapter = getAdapter();
+ if (adapter.isLoading() || mLoadingLookupKey) {
+ return;
+ }
+
+ if (adapter.hasValidSelection()) {
+ mSelectionVerified = true;
+ requestSelectionOnScreenIfNeeded();
+ return;
+ }
+
+ notifyInvalidSelection();
+ }
+
+ public Uri getFirstContactUri() {
+ ContactListAdapter adapter = getAdapter();
+ return adapter.getFirstContactUri();
+ }
+
+ @Override
+ protected void startLoading() {
+ mSelectionVerified = false;
+ super.startLoading();
+ }
+
+ @Override
+ public void reloadData() {
+ mSelectionVerified = false;
+ super.reloadData();
}
public void setOnContactListActionListener(OnContactBrowserActionListener listener) {
@@ -231,6 +281,10 @@
mListener.onSmsContactAction(contactUri);
}
+ private void notifyInvalidSelection() {
+ mListener.onInvalidSelection();
+ }
+
@Override
protected void finish() {
super.finish();
@@ -269,4 +323,10 @@
listView, position + listView.getHeaderViewsCount(), smooth);
}
}
+
+ public void saveSelectedUri(SharedPreferences preferences) {
+ }
+
+ public void restoreSelectedUri(SharedPreferences preferences) {
+ }
}
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index 7e2c4c2..08b3e48 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -30,7 +30,6 @@
import android.widget.ListView;
import android.widget.QuickContactBadge;
-import java.util.List;
/**
* A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type.
@@ -105,7 +104,6 @@
private String mSelectedContactLookupKey;
private ContactListFilter mFilter;
- private List<ContactListFilter> mAllFilters;
public ContactListAdapter(Context context) {
super(context);
@@ -118,22 +116,14 @@
}
/**
- * Returns a full set of all available list filters.
- */
- public List<ContactListFilter> getAllFilters() {
- return mAllFilters;
- }
-
- /**
* Returns the currently selected filter.
*/
public ContactListFilter getFilter() {
return mFilter;
}
- public void setFilter(ContactListFilter filter, List<ContactListFilter> allFilters) {
+ public void setFilter(ContactListFilter filter) {
mFilter = filter;
- mAllFilters = allFilters;
}
public long getSelectedContactDirectoryId() {
@@ -326,4 +316,31 @@
}
return position;
}
+
+ public boolean hasValidSelection() {
+ return getSelectedContactPosition() != -1;
+ }
+
+ public Uri getFirstContactUri() {
+ int partitionCount = getPartitionCount();
+ for (int i = 0; i < partitionCount; i++) {
+ DirectoryPartition partition = (DirectoryPartition) getPartition(i);
+ if (partition.isLoading()) {
+ continue;
+ }
+
+ Cursor cursor = getCursor(i);
+ if (cursor == null) {
+ continue;
+ }
+
+ if (!cursor.moveToFirst()) {
+ continue;
+ }
+
+ return getContactUri(i, cursor);
+ }
+
+ return null;
+ }
}
diff --git a/src/com/android/contacts/list/ContactListFilter.java b/src/com/android/contacts/list/ContactListFilter.java
index 0189bbb..2b212fd 100644
--- a/src/com/android/contacts/list/ContactListFilter.java
+++ b/src/com/android/contacts/list/ContactListFilter.java
@@ -30,6 +30,7 @@
public static final int FILTER_TYPE_CUSTOM = -3;
public static final int FILTER_TYPE_STARRED = -4;
public static final int FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY = -5;
+ public static final int FILTER_TYPE_SINGLE_CONTACT = -6;
public static final int FILTER_TYPE_ACCOUNT = 0;
public static final int FILTER_TYPE_GROUP = 1;
@@ -38,13 +39,16 @@
private static final String KEY_ACCOUNT_NAME = "filter.accountName";
private static final String KEY_ACCOUNT_TYPE = "filter.accountType";
private static final String KEY_GROUP_ID = "filter.groupId";
+ private static final String KEY_GROUP_SOURCE_ID = "filter.groupSourceId";
public int filterType;
public String accountType;
public String accountName;
public Drawable icon;
public long groupId;
+ public String groupSourceId;
public String title;
+ private String mId;
public ContactListFilter(int filterType) {
this.filterType = filterType;
@@ -60,11 +64,12 @@
}
public ContactListFilter(
- String accountType, String accountName, long groupId, String title) {
+ String accountType, String accountName, long groupId, String groupSourceId, String title) {
this.filterType = ContactListFilter.FILTER_TYPE_GROUP;
this.accountType = accountType;
this.accountName = accountName;
this.groupId = groupId;
+ this.groupSourceId = groupSourceId;
this.title = title;
}
@@ -115,7 +120,9 @@
code = code * 31 + accountType.hashCode();
code = code * 31 + accountName.hashCode();
}
- if (groupId != 0) {
+ if (groupSourceId != null) {
+ code = code * 31 + groupSourceId.hashCode();
+ } else if (groupId != 0) {
code = code * 31 + (int) groupId;
}
return code;
@@ -132,10 +139,17 @@
}
ContactListFilter otherFilter = (ContactListFilter) other;
- return filterType == otherFilter.filterType
- && TextUtils.equals(accountName, otherFilter.accountName)
- && TextUtils.equals(accountType, otherFilter.accountType)
- && groupId == otherFilter.groupId;
+ if (filterType != otherFilter.filterType
+ || !TextUtils.equals(accountName, otherFilter.accountName)
+ || !TextUtils.equals(accountType, otherFilter.accountType)) {
+ return false;
+ }
+
+ if (groupSourceId != null && otherFilter.groupSourceId != null) {
+ return groupSourceId.equals(otherFilter.groupSourceId);
+ }
+
+ return groupId == otherFilter.groupId;
}
public static void storeToPreferences(SharedPreferences prefs, ContactListFilter filter) {
@@ -144,6 +158,7 @@
.putString(KEY_ACCOUNT_NAME, filter == null ? null : filter.accountName)
.putString(KEY_ACCOUNT_TYPE, filter == null ? null : filter.accountType)
.putLong(KEY_GROUP_ID, filter == null ? -1 : filter.groupId)
+ .putString(KEY_GROUP_SOURCE_ID, filter == null ? null : filter.groupSourceId)
.apply();
}
@@ -157,6 +172,30 @@
filter.accountName = prefs.getString(KEY_ACCOUNT_NAME, null);
filter.accountType = prefs.getString(KEY_ACCOUNT_TYPE, null);
filter.groupId = prefs.getLong(KEY_GROUP_ID, -1);
+ filter.groupSourceId = prefs.getString(KEY_GROUP_SOURCE_ID, null);
return filter;
}
+
+ /**
+ * Returns a string that can be used as a stable persistent identifier for this filter.
+ */
+ public String getId() {
+ if (mId == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(filterType);
+ if (accountType != null) {
+ sb.append('-').append(accountType);
+ }
+ if (accountName != null) {
+ sb.append('-').append(accountName.replace('-', '_'));
+ }
+ if (groupSourceId != null) {
+ sb.append('-').append(groupSourceId);
+ } else if (groupId != 0) {
+ sb.append('-').append(groupId);
+ }
+ mId = sb.toString();
+ }
+ return mId;
+ }
}
diff --git a/src/com/android/contacts/list/ContactListFilterController.java b/src/com/android/contacts/list/ContactListFilterController.java
index c342d75..4b890cf 100644
--- a/src/com/android/contacts/list/ContactListFilterController.java
+++ b/src/com/android/contacts/list/ContactListFilterController.java
@@ -249,7 +249,9 @@
public void setContactListFilter(ContactListFilter filter, boolean persistent) {
if (!filter.equals(mFilter)) {
mFilter = filter;
- ContactListFilter.storeToPreferences(getSharedPreferences(), mFilter);
+ if (persistent) {
+ ContactListFilter.storeToPreferences(getSharedPreferences(), mFilter);
+ }
if (mListeners != null) {
notifyContactListFilterChanged();
}
diff --git a/src/com/android/contacts/list/ContactListFilterLoader.java b/src/com/android/contacts/list/ContactListFilterLoader.java
index ae791ab..663a6a8 100644
--- a/src/com/android/contacts/list/ContactListFilterLoader.java
+++ b/src/com/android/contacts/list/ContactListFilterLoader.java
@@ -16,8 +16,8 @@
package com.android.contacts.list;
-import com.android.contacts.model.BaseAccountType;
import com.android.contacts.model.AccountTypes;
+import com.android.contacts.model.BaseAccountType;
import android.accounts.Account;
import android.content.AsyncTaskLoader;
@@ -29,7 +29,6 @@
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
/**
@@ -44,6 +43,7 @@
Groups.ACCOUNT_NAME,
Groups.TITLE,
Groups.AUTO_ADD,
+ Groups.SOURCE_ID,
};
public static final int ID = 0;
@@ -51,6 +51,7 @@
public static final int ACCOUNT_NAME = 2;
public static final int TITLE = 3;
public static final int IS_DEFAULT_GROUP = 4; // Using the AUTO_ADD group as default
+ public static final int SOURCE_ID = 5;
private static final String SELECTION =
Groups.DELETED + "=0 AND " + Groups.FAVORITES + "=0";
@@ -74,7 +75,6 @@
results.add(new ContactListFilter(account.type, account.name, icon, account.name));
}
- HashSet<Account> accountsWithGroups = new HashSet<Account>();
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(
@@ -82,6 +82,7 @@
try {
while (cursor.moveToNext()) {
long groupId = cursor.getLong(GroupQuery.ID);
+ String groupSourceId = cursor.getString(GroupQuery.SOURCE_ID);
String accountType = cursor.getString(GroupQuery.ACCOUNT_TYPE);
String accountName = cursor.getString(GroupQuery.ACCOUNT_NAME);
boolean defaultGroup = false;
@@ -94,12 +95,14 @@
if (filter.accountName.equals(accountName)
&& filter.accountType.equals(accountType)) {
filter.groupId = groupId;
+ filter.groupSourceId = groupSourceId;
break;
}
}
} else {
String title = cursor.getString(GroupQuery.TITLE);
- results.add(new ContactListFilter(accountType, accountName, groupId, title));
+ results.add(new ContactListFilter(
+ accountType, accountName, groupId, groupSourceId, title));
}
}
} finally {
diff --git a/src/com/android/contacts/list/ContactListFilterView.java b/src/com/android/contacts/list/ContactListFilterView.java
index e065e91..cb9ec06 100644
--- a/src/com/android/contacts/list/ContactListFilterView.java
+++ b/src/com/android/contacts/list/ContactListFilterView.java
@@ -105,6 +105,10 @@
bindView(0, R.string.list_filter_phones);
break;
}
+ case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT: {
+ bindView(0, R.string.list_filter_single);
+ break;
+ }
case ContactListFilter.FILTER_TYPE_ACCOUNT: {
if (mIcon != null) {
mIcon.setVisibility(View.VISIBLE);
diff --git a/src/com/android/contacts/list/ContactPickerFragment.java b/src/com/android/contacts/list/ContactPickerFragment.java
index 0937608..a0c29e1 100644
--- a/src/com/android/contacts/list/ContactPickerFragment.java
+++ b/src/com/android/contacts/list/ContactPickerFragment.java
@@ -152,7 +152,7 @@
if (!isLegacyCompatibilityMode()) {
DefaultContactListAdapter adapter = new DefaultContactListAdapter(getActivity());
adapter.setFilter(
- new ContactListFilter(ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS), null);
+ new ContactListFilter(ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS));
adapter.setSectionHeaderDisplayEnabled(true);
adapter.setDisplayPhotos(true);
adapter.setQuickContactEnabled(false);
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 651228b..7729e28 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -17,9 +17,10 @@
import com.android.contacts.R;
-import android.app.Activity;
-import android.content.Intent;
+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;
@@ -28,22 +29,23 @@
import android.widget.ProgressBar;
import android.widget.TextView;
+
/**
* 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
- implements ContactListFilterController.ContactListFilterListener {
+public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
private static final String KEY_FILTER_ENABLED = "filterEnabled";
- private static final int REQUEST_CODE_CUSTOMIZE_FILTER = 3;
+ private static final String PERSISTENT_SELECTION_PREFIX = "defaultContactBrowserSelection";
private View mCounterHeaderView;
private View mSearchHeaderView;
private boolean mFilterEnabled;
- private ContactListFilterController mFilterController;
+ private ContactListFilter mFilter;
+ private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX;
public DefaultContactBrowseListFragment() {
setPhotoLoaderEnabled(true);
@@ -51,17 +53,8 @@
setAizyEnabled(true);
}
- public void setContactListFilterController(ContactListFilterController filterController) {
- mFilterController = filterController;
- mFilterController.addListener(this);
- }
-
- @Override
- public void onDetach() {
- if (mFilterController != null) {
- mFilterController.removeListener(this);
- }
- super.onDetach();
+ public void setFilter(ContactListFilter filter) {
+ mFilter = filter;
}
@Override
@@ -99,8 +92,8 @@
super.configureAdapter();
DefaultContactListAdapter adapter = (DefaultContactListAdapter)getAdapter();
- if (adapter != null && mFilterEnabled && mFilterController != null) {
- adapter.setFilter(mFilterController.getFilter(), mFilterController.getFilterList());
+ if (adapter != null && mFilter != null) {
+ adapter.setFilter(mFilter);
}
}
@@ -189,47 +182,47 @@
}
@Override
- protected void startLoading() {
- if (mFilterController != null && !mFilterController.isLoaded()) {
- mFilterController.startLoading();
- }
-
- if (!mFilterEnabled || mFilterController == null || mFilterController.isLoaded()) {
+ public void startLoading() {
+ if (!mFilterEnabled || mFilter != null) {
super.startLoading();
}
}
@Override
- protected void onPartitionLoaded(int partitionIndex, Cursor data) {
- super.onPartitionLoaded(partitionIndex, data);
- if (mFilterController != null) {
- mFilterController.postDelayedRefresh();
+ public void saveSelectedUri(SharedPreferences preferences) {
+ if (isSearchMode()) {
+ return;
+ }
+
+ Editor editor = preferences.edit();
+ Uri uri = getSelectedContactUri();
+ if (uri == null) {
+ editor.remove(getPersistentSelectionKey());
+ } else {
+ editor.putString(getPersistentSelectionKey(), uri.toString());
+ }
+ editor.apply();
+ }
+
+ @Override
+ public void restoreSelectedUri(SharedPreferences preferences) {
+ if (isSearchMode()) {
+ return;
+ }
+
+ String selectedUri = preferences.getString(getPersistentSelectionKey(), null);
+ if (selectedUri == null) {
+ setSelectedContactUri(null);
+ } else {
+ setSelectedContactUri(Uri.parse(selectedUri));
}
}
- @Override
- public void onContactListFiltersLoaded() {
- if (mFilterEnabled) {
- // Filters have been loaded - now we can start loading the list itself
- startLoading();
- }
- }
-
- @Override
- public void onContactListFilterChanged() {
- reloadData();
- }
-
- @Override
- public void onContactListFilterCustomizationRequest() {
- startActivityForResult(new Intent(getContext(), CustomContactListFilterActivity.class),
- REQUEST_CODE_CUSTOMIZE_FILTER);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_CODE_CUSTOMIZE_FILTER && resultCode == Activity.RESULT_OK) {
- mFilterController.selectCustomFilter();
+ private String getPersistentSelectionKey() {
+ if (mFilter == null) {
+ return mPersistentSelectionPrefix;
+ } else {
+ return mPersistentSelectionPrefix + "-" + mFilter.getId();
}
}
}
diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java
index ede3597..577e5bb 100644
--- a/src/com/android/contacts/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/list/DefaultContactListAdapter.java
@@ -17,6 +17,7 @@
import com.android.contacts.preference.ContactsPreferences;
+import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.content.SharedPreferences;
@@ -82,11 +83,20 @@
}
protected void configureUri(CursorLoader loader, long directoryId, ContactListFilter filter) {
- Uri uri;
- if (filter != null && filter.groupId != 0) {
- uri = Data.CONTENT_URI;
- } else {
- uri = Contacts.CONTENT_URI;
+ Uri uri = Contacts.CONTENT_URI;
+ if (filter != null) {
+ if (filter.filterType == ContactListFilter.FILTER_TYPE_GROUP ||
+ filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) {
+ uri = Data.CONTENT_URI;
+ } else if (filter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
+ String lookupKey = getSelectedContactLookupKey();
+ if (lookupKey != null) {
+ uri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
+ } else {
+ // Non-existent contact
+ uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 0);
+ }
+ }
}
if (directoryId == Directory.DEFAULT && isSectionHeaderDisplayEnabled()) {
@@ -94,7 +104,9 @@
}
// The "All accounts" filter is the same as the entire contents of Directory.DEFAULT
- if (filter != null && filter.filterType != ContactListFilter.FILTER_TYPE_CUSTOM) {
+ if (filter != null
+ && filter.filterType != ContactListFilter.FILTER_TYPE_CUSTOM
+ && filter.filterType != ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
uri = uri.buildUpon().appendQueryParameter(
ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
.build();
@@ -130,6 +142,11 @@
// filter
break;
}
+ case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT: {
+ // We have already added the lookup key to the URI, which takes care of this
+ // filter
+ break;
+ }
case ContactListFilter.FILTER_TYPE_STARRED: {
selection.append(Contacts.STARRED + "!=0");
break;
diff --git a/src/com/android/contacts/list/OnContactBrowserActionListener.java b/src/com/android/contacts/list/OnContactBrowserActionListener.java
index 239f8e1..80d4838 100644
--- a/src/com/android/contacts/list/OnContactBrowserActionListener.java
+++ b/src/com/android/contacts/list/OnContactBrowserActionListener.java
@@ -68,4 +68,9 @@
* Closes the contact browser.
*/
void onFinishAction();
+
+ /**
+ * Invoked if the requested selected contact is not found in the list.
+ */
+ void onInvalidSelection();
}