summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/com/android/dialer/searchfragment/common/SearchCursor.java38
-rw-r--r--java/com/android/dialer/searchfragment/cp2/AndroidManifest.xml16
-rw-r--r--java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java (renamed from java/com/android/dialer/searchfragment/cp2/SearchContactCursor.java)6
-rw-r--r--java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java16
-rw-r--r--java/com/android/dialer/searchfragment/cp2/SearchContactsCursor.java64
-rw-r--r--java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java7
-rw-r--r--java/com/android/dialer/searchfragment/cp2/res/values/strings.xml20
-rw-r--r--java/com/android/dialer/searchfragment/list/NewSearchFragment.java12
-rw-r--r--java/com/android/dialer/searchfragment/list/SearchAdapter.java25
-rw-r--r--java/com/android/dialer/searchfragment/list/SearchCursorManager.java119
-rw-r--r--java/com/android/dialer/searchfragment/nearbyplaces/AndroidManifest.xml2
-rw-r--r--java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursor.java64
-rw-r--r--java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java6
-rw-r--r--java/com/android/dialer/searchfragment/testing/TestSearchCursor.java47
14 files changed, 338 insertions, 104 deletions
diff --git a/java/com/android/dialer/searchfragment/common/SearchCursor.java b/java/com/android/dialer/searchfragment/common/SearchCursor.java
new file mode 100644
index 000000000..368ee09d6
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/common/SearchCursor.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.searchfragment.common;
+
+import android.database.Cursor;
+import android.support.annotation.NonNull;
+
+/** Base cursor interface needed for all cursors used in search. */
+public interface SearchCursor extends Cursor {
+
+ String[] HEADER_PROJECTION = {"header_text"};
+
+ int HEADER_TEXT_POSITION = 0;
+
+ /** Returns true if the current cursor position is a header */
+ boolean isHeader();
+
+ /**
+ * Notifies the cursor that the query has updated.
+ *
+ * @return true if the data set has changed.
+ */
+ boolean updateQuery(@NonNull String query);
+}
diff --git a/java/com/android/dialer/searchfragment/cp2/AndroidManifest.xml b/java/com/android/dialer/searchfragment/cp2/AndroidManifest.xml
new file mode 100644
index 000000000..8d2efca40
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/cp2/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<manifest package="com.android.dialer.searchfragment.cp2"/> \ No newline at end of file
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactCursor.java b/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
index 05e98cc84..d5fcfba4f 100644
--- a/java/com/android/dialer/searchfragment/cp2/SearchContactCursor.java
+++ b/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
@@ -34,12 +34,12 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Wrapper for a cursor returned by {@link SearchContactsCursorLoader}.
+ * Wrapper for a cursor containing all on device contacts.
*
* <p>This cursor removes duplicate phone numbers associated with the same contact and can filter
* contacts based on a query by calling {@link #filter(String)}.
*/
-public final class SearchContactCursor implements Cursor {
+final class ContactFilterCursor implements Cursor {
private final Cursor cursor;
// List of cursor ids that are valid for displaying after filtering.
@@ -66,7 +66,7 @@ public final class SearchContactCursor implements Cursor {
* @param cursor with projection {@link Projections#PHONE_PROJECTION}.
* @param query to filter cursor results.
*/
- public SearchContactCursor(Cursor cursor, @Nullable String query) {
+ ContactFilterCursor(Cursor cursor, @Nullable String query) {
// TODO(calderwoodra) investigate copying this into a MatrixCursor and holding in memory
this.cursor = cursor;
filter(query);
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java b/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java
index 4b5cab901..2bd9cdd8a 100644
--- a/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java
+++ b/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java
@@ -38,6 +38,7 @@ import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.searchfragment.common.Projections;
import com.android.dialer.searchfragment.common.QueryBoldingUtil;
import com.android.dialer.searchfragment.common.R;
+import com.android.dialer.searchfragment.common.SearchCursor;
import com.android.dialer.telecom.TelecomUtil;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -77,7 +78,7 @@ public final class SearchContactViewHolder extends ViewHolder implements OnClick
* Binds the ViewHolder with a cursor from {@link SearchContactsCursorLoader} with the data found
* at the cursors set position.
*/
- public void bind(Cursor cursor, String query) {
+ public void bind(SearchCursor cursor, String query) {
number = cursor.getString(Projections.PHONE_NUMBER);
String name = cursor.getString(Projections.PHONE_DISPLAY_NAME);
String label = getLabel(context.getResources(), cursor);
@@ -109,17 +110,18 @@ public final class SearchContactViewHolder extends ViewHolder implements OnClick
}
}
- private boolean shouldShowPhoto(Cursor cursor) {
+ private boolean shouldShowPhoto(SearchCursor cursor) {
int currentPosition = cursor.getPosition();
- if (currentPosition == 0) {
- return true;
- } else {
- String currentLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY);
- cursor.moveToPosition(currentPosition - 1);
+ String currentLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY);
+ cursor.moveToPosition(currentPosition - 1);
+
+ if (!cursor.isHeader() && !cursor.isBeforeFirst()) {
String previousLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY);
cursor.moveToPosition(currentPosition);
return !currentLookupKey.equals(previousLookupKey);
}
+ cursor.moveToPosition(currentPosition);
+ return true;
}
private static Uri getContactUri(Cursor cursor) {
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursor.java b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursor.java
new file mode 100644
index 000000000..18c9ecd7f
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursor.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.searchfragment.cp2;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
+import android.support.annotation.Nullable;
+import com.android.dialer.searchfragment.common.SearchCursor;
+
+/**
+ * {@link SearchCursor} implementation for displaying on device contacts.
+ *
+ * <p>Inserts header "All Contacts" at position 0.
+ */
+final class SearchContactsCursor extends MergeCursor implements SearchCursor {
+
+ private final ContactFilterCursor contactFilterCursor;
+
+ public static SearchContactsCursor newInstnace(
+ Context context, ContactFilterCursor contactFilterCursor) {
+ MatrixCursor headerCursor = new MatrixCursor(HEADER_PROJECTION);
+ headerCursor.addRow(new String[] {context.getString(R.string.all_contacts)});
+ return new SearchContactsCursor(new Cursor[] {headerCursor, contactFilterCursor});
+ }
+
+ private SearchContactsCursor(Cursor[] cursors) {
+ super(cursors);
+ contactFilterCursor = (ContactFilterCursor) cursors[1];
+ }
+
+ @Override
+ public boolean isHeader() {
+ return isFirst();
+ }
+
+ @Override
+ public boolean updateQuery(@Nullable String query) {
+ contactFilterCursor.filter(query);
+ return true;
+ }
+
+ @Override
+ public int getCount() {
+ // If we don't have any contents, we don't want to show the header
+ int count = contactFilterCursor.getCount();
+ return count == 0 ? 0 : count + 1;
+ }
+}
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
index c72f28b25..d75a66122 100644
--- a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
@@ -37,6 +37,11 @@ public final class SearchContactsCursorLoader extends CursorLoader {
@Override
public Cursor loadInBackground() {
- return new SearchContactCursor(super.loadInBackground(), null);
+ // All contacts
+ Cursor cursor = super.loadInBackground();
+ // Filtering logic
+ ContactFilterCursor contactFilterCursor = new ContactFilterCursor(cursor, null);
+ // Header logic
+ return SearchContactsCursor.newInstnace(getContext(), contactFilterCursor);
}
}
diff --git a/java/com/android/dialer/searchfragment/cp2/res/values/strings.xml b/java/com/android/dialer/searchfragment/cp2/res/values/strings.xml
new file mode 100644
index 000000000..5462dc926
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/cp2/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+ <!-- Label for a list of all contacts on device. [CHAR LIMIT=30]-->
+ <string name="all_contacts">All contacts</string>
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index 70358bb16..1a489513c 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -34,8 +34,10 @@ import android.view.ViewGroup;
import android.view.animation.Interpolator;
import com.android.contacts.common.extensions.PhoneDirectoryExtenderAccessor;
import com.android.dialer.animation.AnimUtils;
+import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.searchfragment.common.SearchCursor;
import com.android.dialer.searchfragment.cp2.SearchContactsCursorLoader;
import com.android.dialer.searchfragment.nearbyplaces.NearbyPlacesCursorLoader;
import com.android.dialer.util.PermissionsUtil;
@@ -72,7 +74,7 @@ public final class NewSearchFragment extends Fragment
public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle bundle) {
View view = inflater.inflate(R.layout.fragment_search, parent, false);
- adapter = new SearchAdapter(getContext());
+ adapter = new SearchAdapter(getContext(), new SearchCursorManager());
emptyContentView = view.findViewById(R.id.empty_view);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
@@ -113,10 +115,14 @@ public final class NewSearchFragment extends Fragment
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ if (!(cursor instanceof SearchCursor)) {
+ throw Assert.createIllegalStateFailException("Cursors must implement SearchCursor");
+ }
+
if (loader instanceof SearchContactsCursorLoader) {
- adapter.setContactsCursor(cursor);
+ adapter.setContactsCursor((SearchCursor) cursor);
} else if (loader instanceof NearbyPlacesCursorLoader) {
- adapter.setNearbyPlacesCursor(cursor);
+ adapter.setNearbyPlacesCursor((SearchCursor) cursor);
} else {
throw new IllegalStateException("Invalid loader: " + loader);
}
diff --git a/java/com/android/dialer/searchfragment/list/SearchAdapter.java b/java/com/android/dialer/searchfragment/list/SearchAdapter.java
index faa80fe85..c8588fc7d 100644
--- a/java/com/android/dialer/searchfragment/list/SearchAdapter.java
+++ b/java/com/android/dialer/searchfragment/list/SearchAdapter.java
@@ -17,12 +17,12 @@
package com.android.dialer.searchfragment.list;
import android.content.Context;
-import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.android.dialer.common.Assert;
+import com.android.dialer.searchfragment.common.SearchCursor;
import com.android.dialer.searchfragment.cp2.SearchContactViewHolder;
import com.android.dialer.searchfragment.list.SearchCursorManager.RowType;
import com.android.dialer.searchfragment.nearbyplaces.NearbyPlaceViewHolder;
@@ -35,9 +35,9 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> {
private String query;
- SearchAdapter(Context context) {
- searchCursorManager = new SearchCursorManager();
+ SearchAdapter(Context context, SearchCursorManager searchCursorManager) {
this.context = context;
+ this.searchCursorManager = searchCursorManager;
}
@Override
@@ -49,6 +49,7 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> {
case RowType.NEARBY_PLACES_ROW:
return new NearbyPlaceViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false));
+ case RowType.CONTACT_HEADER:
case RowType.DIRECTORY_HEADER:
case RowType.NEARBY_PLACES_HEADER:
return new HeaderViewHolder(
@@ -68,20 +69,17 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder instanceof SearchContactViewHolder) {
- Cursor cursor = searchCursorManager.getCursor(position);
- ((SearchContactViewHolder) holder).bind(cursor, query);
+ ((SearchContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof NearbyPlaceViewHolder) {
- Cursor cursor = searchCursorManager.getCursor(position);
- ((NearbyPlaceViewHolder) holder).bind(cursor, query);
+ ((NearbyPlaceViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof HeaderViewHolder) {
- String header = context.getString(searchCursorManager.getHeaderText(position));
- ((HeaderViewHolder) holder).setHeader(header);
+ ((HeaderViewHolder) holder).setHeader(searchCursorManager.getHeaderText(position));
} else {
throw Assert.createIllegalStateFailException("Invalid ViewHolder: " + holder);
}
}
- void setContactsCursor(Cursor cursor) {
+ void setContactsCursor(SearchCursor cursor) {
searchCursorManager.setContactsCursor(cursor);
notifyDataSetChanged();
}
@@ -97,11 +95,12 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> {
public void setQuery(String query) {
this.query = query;
- searchCursorManager.setQuery(query);
- notifyDataSetChanged();
+ if (searchCursorManager.setQuery(query)) {
+ notifyDataSetChanged();
+ }
}
- public void setNearbyPlacesCursor(Cursor nearbyPlacesCursor) {
+ public void setNearbyPlacesCursor(SearchCursor nearbyPlacesCursor) {
searchCursorManager.setNearbyPlacesCursor(nearbyPlacesCursor);
notifyDataSetChanged();
}
diff --git a/java/com/android/dialer/searchfragment/list/SearchCursorManager.java b/java/com/android/dialer/searchfragment/list/SearchCursorManager.java
index 45d66aab8..68f770af9 100644
--- a/java/com/android/dialer/searchfragment/list/SearchCursorManager.java
+++ b/java/com/android/dialer/searchfragment/list/SearchCursorManager.java
@@ -16,11 +16,9 @@
package com.android.dialer.searchfragment.list;
-import android.database.Cursor;
import android.support.annotation.IntDef;
-import android.support.annotation.StringRes;
import com.android.dialer.common.Assert;
-import com.android.dialer.searchfragment.cp2.SearchContactCursor;
+import com.android.dialer.searchfragment.common.SearchCursor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -30,9 +28,9 @@ import java.lang.annotation.RetentionPolicy;
* <p>This class accepts three cursors:
*
* <ul>
- * <li>A contacts cursor {@link #setContactsCursor(Cursor)}
- * <li>A google search results cursor {@link #setNearbyPlacesCursor(Cursor)}
- * <li>A work directory cursor {@link #setCorpDirectoryCursor(Cursor)}
+ * <li>A contacts cursor {@link #setContactsCursor(SearchCursor)}
+ * <li>A google search results cursor {@link #setNearbyPlacesCursor(SearchCursor)}
+ * <li>A work directory cursor {@link #setCorpDirectoryCursor(SearchCursor)}
* </ul>
*
* <p>The key purpose of this class is to compose three aforementioned cursors together to function
@@ -50,6 +48,7 @@ final class SearchCursorManager {
@Retention(RetentionPolicy.SOURCE)
@IntDef({
SearchCursorManager.RowType.INVALID,
+ SearchCursorManager.RowType.CONTACT_HEADER,
SearchCursorManager.RowType.CONTACT_ROW,
SearchCursorManager.RowType.NEARBY_PLACES_HEADER,
SearchCursorManager.RowType.NEARBY_PLACES_ROW,
@@ -58,23 +57,25 @@ final class SearchCursorManager {
})
@interface RowType {
int INVALID = 0;
+ /** Header to mark the start of contact rows. */
+ int CONTACT_HEADER = 1;
/** A row containing contact information for contacts stored locally on device. */
- int CONTACT_ROW = 1;
+ int CONTACT_ROW = 2;
/** Header to mark the end of contact rows and start of nearby places rows. */
- int NEARBY_PLACES_HEADER = 2;
+ int NEARBY_PLACES_HEADER = 3;
/** A row containing nearby places information/search results. */
- int NEARBY_PLACES_ROW = 3;
+ int NEARBY_PLACES_ROW = 4;
/** Header to mark the end of the previous row set and start of directory rows. */
- int DIRECTORY_HEADER = 4;
+ int DIRECTORY_HEADER = 5;
/** A row containing contact information for contacts stored externally in corp directories. */
- int DIRECTORY_ROW = 5;
+ int DIRECTORY_ROW = 6;
}
- private Cursor contactsCursor = null;
- private Cursor nearbyPlacesCursor = null;
- private Cursor corpDirectoryCursor = null;
+ private SearchCursor contactsCursor = null;
+ private SearchCursor nearbyPlacesCursor = null;
+ private SearchCursor corpDirectoryCursor = null;
- void setContactsCursor(Cursor cursor) {
+ void setContactsCursor(SearchCursor cursor) {
if (cursor == contactsCursor) {
return;
}
@@ -90,7 +91,7 @@ final class SearchCursorManager {
}
}
- void setNearbyPlacesCursor(Cursor cursor) {
+ void setNearbyPlacesCursor(SearchCursor cursor) {
if (cursor == nearbyPlacesCursor) {
return;
}
@@ -106,7 +107,7 @@ final class SearchCursorManager {
}
}
- void setCorpDirectoryCursor(Cursor cursor) {
+ void setCorpDirectoryCursor(SearchCursor cursor) {
if (cursor == corpDirectoryCursor) {
return;
}
@@ -122,14 +123,23 @@ final class SearchCursorManager {
}
}
- void setQuery(String query) {
+ boolean setQuery(String query) {
+ boolean updated = false;
if (contactsCursor != null) {
- // TODO(calderwoodra): abstract this
- ((SearchContactCursor) contactsCursor).filter(query);
+ updated = contactsCursor.updateQuery(query);
}
+
+ if (nearbyPlacesCursor != null) {
+ updated |= nearbyPlacesCursor.updateQuery(query);
+ }
+
+ if (corpDirectoryCursor != null) {
+ updated |= corpDirectoryCursor.updateQuery(query);
+ }
+ return updated;
}
- /** @return the sum of counts of all cursors, including headers. */
+ /** Returns the sum of counts of all cursors, including headers. */
int getCount() {
int count = 0;
if (contactsCursor != null) {
@@ -137,12 +147,10 @@ final class SearchCursorManager {
}
if (nearbyPlacesCursor != null) {
- count++; // header
count += nearbyPlacesCursor.getCount();
}
if (corpDirectoryCursor != null) {
- count++; // header
count += corpDirectoryCursor.getCount();
}
@@ -151,54 +159,30 @@ final class SearchCursorManager {
@RowType
int getRowType(int position) {
- if (contactsCursor != null) {
- position -= contactsCursor.getCount();
-
- if (position < 0) {
- return SearchCursorManager.RowType.CONTACT_ROW;
- }
+ SearchCursor cursor = getCursor(position);
+ if (cursor == contactsCursor) {
+ return cursor.isHeader() ? RowType.CONTACT_HEADER : RowType.CONTACT_ROW;
}
- if (nearbyPlacesCursor != null) {
- if (position == 0) {
- return SearchCursorManager.RowType.NEARBY_PLACES_HEADER;
- } else {
- position--; // header
- }
-
- position -= nearbyPlacesCursor.getCount();
-
- if (position < 0) {
- return SearchCursorManager.RowType.NEARBY_PLACES_ROW;
- }
+ if (cursor == nearbyPlacesCursor) {
+ return cursor.isHeader() ? RowType.NEARBY_PLACES_HEADER : RowType.NEARBY_PLACES_ROW;
}
- if (corpDirectoryCursor != null) {
- if (position == 0) {
- return SearchCursorManager.RowType.DIRECTORY_HEADER;
- } else {
- position--; // header
- }
-
- position -= corpDirectoryCursor.getCount();
-
- if (position < 0) {
- return SearchCursorManager.RowType.DIRECTORY_ROW;
- }
+ if (cursor == corpDirectoryCursor) {
+ return cursor.isHeader() ? RowType.DIRECTORY_HEADER : RowType.DIRECTORY_ROW;
}
-
throw Assert.createIllegalStateFailException("No valid row type.");
}
/**
- * Gets cursor corresponding to position in coelesced list of search cursors. Callers should
+ * Gets cursor corresponding to position in coalesced list of search cursors. Callers should
* ensure that {@link #getRowType(int)} doesn't correspond to header position, otherwise an
* exception will be thrown.
*
- * @param position in coalecsed list of search cursors
+ * @param position in coalesced list of search cursors
* @return Cursor moved to position specific to passed in position.
*/
- Cursor getCursor(int position) {
+ SearchCursor getCursor(int position) {
if (contactsCursor != null) {
int count = contactsCursor.getCount();
@@ -210,8 +194,6 @@ final class SearchCursorManager {
}
if (nearbyPlacesCursor != null) {
- Assert.checkArgument(position != 0, "No valid cursor, position is nearby places header.");
- position--; // header
int count = nearbyPlacesCursor.getCount();
if (position - count < 0) {
@@ -222,8 +204,6 @@ final class SearchCursorManager {
}
if (corpDirectoryCursor != null) {
- Assert.checkArgument(position != 0, "No valid cursor, position is directory search header.");
- position--; // header
int count = corpDirectoryCursor.getCount();
if (position - count < 0) {
@@ -236,21 +216,8 @@ final class SearchCursorManager {
throw Assert.createIllegalStateFailException("No valid cursor.");
}
- @StringRes
- int getHeaderText(int position) {
- @RowType int rowType = getRowType(position);
- switch (rowType) {
- case RowType.NEARBY_PLACES_HEADER:
- return R.string.nearby_places;
- case RowType.DIRECTORY_HEADER: // TODO(calderwoodra)
- case RowType.DIRECTORY_ROW:
- case RowType.CONTACT_ROW:
- case RowType.NEARBY_PLACES_ROW:
- case RowType.INVALID:
- default:
- throw Assert.createIllegalStateFailException(
- "Invalid row type, position " + position + " is rowtype " + rowType);
- }
+ String getHeaderText(int position) {
+ return getCursor(position).getString(SearchCursor.HEADER_TEXT_POSITION);
}
/** removes all cursors. */
diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/AndroidManifest.xml b/java/com/android/dialer/searchfragment/nearbyplaces/AndroidManifest.xml
index 178cd83c3..52fb08671 100644
--- a/java/com/android/dialer/searchfragment/nearbyplaces/AndroidManifest.xml
+++ b/java/com/android/dialer/searchfragment/nearbyplaces/AndroidManifest.xml
@@ -13,4 +13,4 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<manifest package="com.android.dialer.searchfragment.common"/> \ No newline at end of file
+<manifest package="com.android.dialer.searchfragment.nearbyplaces"/> \ No newline at end of file
diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursor.java b/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursor.java
new file mode 100644
index 000000000..a4142a41d
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursor.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.searchfragment.nearbyplaces;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
+import android.support.annotation.Nullable;
+import com.android.dialer.searchfragment.common.SearchCursor;
+
+/** {@link SearchCursor} implementation for displaying on nearby places. */
+final class NearbyPlacesCursor extends MergeCursor implements SearchCursor {
+
+ private final Cursor nearbyPlacesCursor;
+
+ public static NearbyPlacesCursor newInstnace(Context context, Cursor nearbyPlacesCursor) {
+ MatrixCursor headerCursor = new MatrixCursor(HEADER_PROJECTION);
+ headerCursor.addRow(new String[] {context.getString(R.string.nearby_places)});
+ return new NearbyPlacesCursor(new Cursor[] {headerCursor, nearbyPlacesCursor});
+ }
+
+ private NearbyPlacesCursor(Cursor[] cursors) {
+ super(cursors);
+ nearbyPlacesCursor = cursors[1];
+ }
+
+ @Override
+ public boolean isHeader() {
+ return isFirst();
+ }
+
+ @Override
+ public boolean updateQuery(@Nullable String query) {
+ // When the query changes, a new network request is made for nearby places. Meaning this cursor
+ // will be closed and another created, so return false.
+ return false;
+ }
+
+ @Override
+ public int getCount() {
+ // If we don't have any contents, we don't want to show the header
+ if (nearbyPlacesCursor == null || nearbyPlacesCursor.isClosed()) {
+ return 0;
+ }
+
+ int count = nearbyPlacesCursor.getCount();
+ return count == 0 ? 0 : count + 1;
+ }
+}
diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java b/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java
index 9f3193e92..6807a6e6b 100644
--- a/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java
@@ -18,6 +18,7 @@ package com.android.dialer.searchfragment.nearbyplaces;
import android.content.Context;
import android.content.CursorLoader;
+import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import com.android.contacts.common.extensions.PhoneDirectoryExtenderAccessor;
@@ -32,6 +33,11 @@ public final class NearbyPlacesCursorLoader extends CursorLoader {
super(context, getContentUri(context, query), Projections.PHONE_PROJECTION, null, null, null);
}
+ @Override
+ public Cursor loadInBackground() {
+ return NearbyPlacesCursor.newInstnace(getContext(), super.loadInBackground());
+ }
+
private static Uri getContentUri(Context context, String query) {
return PhoneDirectoryExtenderAccessor.get(context)
.getContentUri()
diff --git a/java/com/android/dialer/searchfragment/testing/TestSearchCursor.java b/java/com/android/dialer/searchfragment/testing/TestSearchCursor.java
new file mode 100644
index 000000000..9a0b95789
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/testing/TestSearchCursor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dialer.searchfragment.testing;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
+import android.support.annotation.Nullable;
+import com.android.dialer.searchfragment.common.SearchCursor;
+
+/** {@link SearchCursor} implementation useful for testing with a header inserted at position 0. */
+public final class TestSearchCursor extends MergeCursor implements SearchCursor {
+
+ public static TestSearchCursor newInstance(Cursor cursor, String header) {
+ MatrixCursor headerRow = new MatrixCursor(HEADER_PROJECTION);
+ headerRow.addRow(new String[] {header});
+ return new TestSearchCursor(new Cursor[] {headerRow, cursor});
+ }
+
+ private TestSearchCursor(Cursor[] cursors) {
+ super(cursors);
+ }
+
+ @Override
+ public boolean isHeader() {
+ return isFirst();
+ }
+
+ @Override
+ public boolean updateQuery(@Nullable String query) {
+ return false;
+ }
+}