summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Mak <tonymak@google.com>2016-05-16 15:43:54 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-05-16 15:43:54 +0000
commit47037f9fef1abf08c513983e9f73e39d82bcd32d (patch)
treeb669f6cf8e5e7f0b58e50abbff18f4bbca802d76
parent3a1468db129425744078f6267d7f10ad1c13641f (diff)
parent904516077182cce4ce71a51b27a3ab418ed0f225 (diff)
downloadandroid_packages_apps_Messaging-47037f9fef1abf08c513983e9f73e39d82bcd32d.tar.gz
android_packages_apps_Messaging-47037f9fef1abf08c513983e9f73e39d82bcd32d.tar.bz2
android_packages_apps_Messaging-47037f9fef1abf08c513983e9f73e39d82bcd32d.zip
Separate work and personal contacts search result
am: 9045160771 * commit '904516077182cce4ce71a51b27a3ab418ed0f225': Separate work and personal contacts search result Change-Id: I302cac2ded10c1945fb708996809a15cc8cebd28
-rw-r--r--res/layout/work_directory_header.xml24
-rw-r--r--res/values/dimens.xml6
-rw-r--r--res/values/strings.xml2
-rw-r--r--res/values/styles.xml10
-rw-r--r--src/com/android/messaging/ui/contact/ContactRecipientAdapter.java257
5 files changed, 238 insertions, 61 deletions
diff --git a/res/layout/work_directory_header.xml b/res/layout/work_directory_header.xml
new file mode 100644
index 0000000..3c882f5
--- /dev/null
+++ b/res/layout/work_directory_header.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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 A`NY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Layout used for list section separators. -->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:text="@string/work_directory_display_name"
+ style="@style/DirectoryHeaderStyle"
+ />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 270ea9e..5ff0eb7 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -188,4 +188,10 @@
<dimen name="fastscroll_preview_margin_left_right">8dp</dimen>
<dimen name="fastscroll_preview_text_size">24sp</dimen>
+ <dimen name="directory_header_padding_start">16dp</dimen>
+ <dimen name="directory_header_padding_end">32dp</dimen>
+ <dimen name="directory_header_padding_top">18dp</dimen>
+ <dimen name="directory_header_padding_bottom">8dp</dimen>
+ <dimen name="directory_header_text_size">14sp</dimen>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 58af39b..012d87f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -973,4 +973,6 @@
<!-- The accessibility text read when the sim chooser pops up to read the current selected sim -->
<string name="selected_sim_content_message"><xliff:g id="selected_sim">%s</xliff:g> selected</string>
+
+ <string name="work_directory_display_name">Work Profile contacts</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index d45f2e1..582c755 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -623,4 +623,14 @@
<item name="android:textColor">@android:color/white</item>
<item name="android:gravity">center</item>
</style>
+ <style name="DirectoryHeaderStyle">
+ <item name="android:paddingLeft">@dimen/directory_header_padding_start</item>
+ <item name="android:paddingStart">@dimen/directory_header_padding_start</item>
+ <item name="android:paddingRight">@dimen/directory_header_padding_end</item>
+ <item name="android:paddingEnd">@dimen/directory_header_padding_end</item>
+ <item name="android:paddingTop">@dimen/directory_header_padding_top</item>
+ <item name="android:paddingBottom">@dimen/directory_header_padding_bottom</item>
+ <item name="android:textSize">@dimen/directory_header_text_size</item>
+ <item name="android:textStyle">bold</item>
+ </style>
</resources>
diff --git a/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java b/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java
index 240f281..1d91241 100644
--- a/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java
+++ b/src/com/android/messaging/ui/contact/ContactRecipientAdapter.java
@@ -22,12 +22,17 @@ import android.support.v4.util.Pair;
import android.text.TextUtils;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.Filter;
+import android.widget.TextView;
import com.android.ex.chips.BaseRecipientAdapter;
import com.android.ex.chips.RecipientAlternatesAdapter;
import com.android.ex.chips.RecipientAlternatesAdapter.RecipientMatchCallback;
import com.android.ex.chips.RecipientEntry;
+import com.android.messaging.R;
import com.android.messaging.util.Assert;
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
import com.android.messaging.util.BugleGservices;
@@ -54,6 +59,18 @@ import java.util.Map;
* for {@link ContactRecipientAutoCompleteView}
*/
public final class ContactRecipientAdapter extends BaseRecipientAdapter {
+ private static final int WORD_DIRECTORY_HEADER_POS_NONE = -1;
+ /**
+ * Stores the index of work directory header.
+ */
+ private int mWorkDirectoryHeaderPos = WORD_DIRECTORY_HEADER_POS_NONE;
+ private final LayoutInflater mInflater;
+
+ /**
+ * Type of directory entry.
+ */
+ private static final int ENTRY_TYPE_DIRECTORY = RecipientEntry.ENTRY_TYPE_SIZE;
+
public ContactRecipientAdapter(final Context context,
final ContactListItemView.HostInterface clivHost) {
this(context, Integer.MAX_VALUE, QUERY_TYPE_PHONE, clivHost);
@@ -63,6 +80,7 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
final int queryMode, final ContactListItemView.HostInterface clivHost) {
super(context, preferredMaxResultCount, queryMode);
setPhotoManager(new ContactRecipientPhotoManager(context, clivHost));
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
@@ -82,6 +100,7 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
* results.
*/
public class ContactFilter extends Filter {
+
// Used to sort filtered contacts when it has combined results from email and phone.
private final RecipientEntryComparator mComparator = new RecipientEntryComparator();
@@ -96,8 +115,7 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
* return the merged results.
*/
@DoesNotRunOnMainThread
- private Pair<Cursor, Boolean> getFilteredResultsCursor(final Context context,
- final String searchText) {
+ private CursorResult getFilteredResultsCursor(final String searchText) {
Assert.isNotMainThread();
if (BugleGservices.get().getBoolean(
BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS,
@@ -107,44 +125,35 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
.filterPhones(getContext(), searchText).performSynchronousQuery();
final Cursor personalFilterEmailsCursor = ContactUtil
.filterEmails(getContext(), searchText).performSynchronousQuery();
- Cursor resultCursor;
+ final Cursor personalCursor = new MergeCursor(
+ new Cursor[]{personalFilterEmailsCursor, personalFilterPhonesCursor});
+ final CursorResult cursorResult =
+ new CursorResult(personalCursor, false /* sorted */);
if (OsUtil.isAtLeastN()) {
// Including enterprise result starting from N.
final Cursor enterpriseFilterPhonesCursor = ContactUtil.filterPhonesEnterprise(
getContext(), searchText).performSynchronousQuery();
final Cursor enterpriseFilterEmailsCursor = ContactUtil.filterEmailsEnterprise(
getContext(), searchText).performSynchronousQuery();
- // TODO: Separating enterprise result from personal result (b/26021888)
- resultCursor = new MergeCursor(
- new Cursor[]{personalFilterEmailsCursor, enterpriseFilterEmailsCursor,
- personalFilterPhonesCursor, enterpriseFilterPhonesCursor});
- } else {
- resultCursor = new MergeCursor(
- new Cursor[]{personalFilterEmailsCursor, personalFilterPhonesCursor});
+ final Cursor enterpriseCursor = new MergeCursor(
+ new Cursor[]{enterpriseFilterEmailsCursor,
+ enterpriseFilterPhonesCursor});
+ cursorResult.enterpriseCursor = enterpriseCursor;
}
- return Pair.create(
- resultCursor,
- false /* the merged cursor is not sorted */
- );
+ return cursorResult;
} else {
final Cursor personalFilterDestinationCursor = ContactUtil
.filterDestination(getContext(), searchText).performSynchronousQuery();
- Cursor resultCursor;
- boolean sorted;
+ final CursorResult cursorResult = new CursorResult(personalFilterDestinationCursor,
+ true);
if (OsUtil.isAtLeastN()) {
// Including enterprise result starting from N.
final Cursor enterpriseFilterDestinationCursor = ContactUtil
.filterDestinationEnterprise(getContext(), searchText)
.performSynchronousQuery();
- // TODO: Separating enterprise result from personal result (b/26021888)
- resultCursor = new MergeCursor(new Cursor[]{personalFilterDestinationCursor,
- enterpriseFilterDestinationCursor});
- sorted = false;
- } else {
- resultCursor = personalFilterDestinationCursor;
- sorted = true;
+ cursorResult.enterpriseCursor = enterpriseFilterDestinationCursor;
}
- return Pair.create(resultCursor, sorted);
+ return cursorResult;
}
}
@@ -163,44 +172,57 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
// Query for auto-complete results, since performFiltering() is not done on the
// main thread, perform the cursor loader queries directly.
- final Pair<Cursor, Boolean> filteredResults = getFilteredResultsCursor(getContext(),
- searchText);
- final Cursor cursor = filteredResults.first;
- final boolean sorted = filteredResults.second;
- if (cursor != null) {
- try {
- final List<RecipientEntry> entries = new ArrayList<RecipientEntry>();
- // First check if the constraint is a valid SMS destination. If so, add the
- // destination as a suggestion item to the drop down.
- if (PhoneUtils.isValidSmsMmsDestination(searchText)) {
- entries.add(ContactRecipientEntryUtils
- .constructSendToDestinationEntry(searchText));
- }
+ final CursorResult cursorResult = getFilteredResultsCursor(searchText);
+ final List<RecipientEntry> entries = new ArrayList<>();
+
+ // First check if the constraint is a valid SMS destination. If so, add the
+ // destination as a suggestion item to the drop down.
+ if (PhoneUtils.isValidSmsMmsDestination(searchText)) {
+ entries.add(ContactRecipientEntryUtils
+ .constructSendToDestinationEntry(searchText));
+ }
+
+ // Only show work directory header if more than one result in work directory.
+ int workDirectoryHeaderPos = WORD_DIRECTORY_HEADER_POS_NONE;
+ if (cursorResult.enterpriseCursor != null
+ && cursorResult.enterpriseCursor.getCount() > 0) {
+ if (cursorResult.personalCursor != null) {
+ workDirectoryHeaderPos = entries.size();
+ workDirectoryHeaderPos += cursorResult.personalCursor.getCount();
+ }
+ }
- HashSet<Long> existingContactIds = new HashSet<Long>();
- while (cursor.moveToNext()) {
- // Make sure there's only one first-level contact (i.e. contact for which
- // we show the avatar picture and name) for every contact id.
- final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
- final boolean isFirstLevel = !existingContactIds.contains(contactId);
- if (isFirstLevel) {
- existingContactIds.add(contactId);
+ final Cursor[] cursors = new Cursor[]{cursorResult.personalCursor,
+ cursorResult.enterpriseCursor};
+ for (Cursor cursor : cursors) {
+ if (cursor != null) {
+ try {
+ final List<RecipientEntry> tempEntries = new ArrayList<>();
+ HashSet<Long> existingContactIds = new HashSet<>();
+ while (cursor.moveToNext()) {
+ // Make sure there's only one first-level contact (i.e. contact for
+ // which we show the avatar picture and name) for every contact id.
+ final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
+ final boolean isFirstLevel = !existingContactIds.contains(contactId);
+ if (isFirstLevel) {
+ existingContactIds.add(contactId);
+ }
+ tempEntries.add(ContactUtil.createRecipientEntryForPhoneQuery(cursor,
+ isFirstLevel));
}
- entries.add(ContactUtil.createRecipientEntryForPhoneQuery(cursor,
- isFirstLevel));
- }
- if (!sorted) {
- Collections.sort(entries, mComparator);
+ if (!cursorResult.isSorted) {
+ Collections.sort(tempEntries, mComparator);
+ }
+ entries.addAll(tempEntries);
+ } finally {
+ cursor.close();
}
- results.values = entries;
- results.count = 1;
-
- } finally {
- cursor.close();
}
}
+ results.values = new ContactReceipientFilterResult(entries, workDirectoryHeaderPos);
+ results.count = 1;
return results;
}
@@ -209,16 +231,20 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
mCurrentConstraint = constraint;
clearTempEntries();
- if (results.values != null) {
- @SuppressWarnings("unchecked")
- final List<RecipientEntry> entries = (List<RecipientEntry>) results.values;
- updateEntries(entries);
- } else {
- updateEntries(Collections.<RecipientEntry>emptyList());
+ final ContactReceipientFilterResult contactReceipientFilterResult
+ = (ContactReceipientFilterResult) results.values;
+ if (contactReceipientFilterResult != null) {
+ mWorkDirectoryHeaderPos = contactReceipientFilterResult.workDirectoryPos;
+ if (contactReceipientFilterResult.recipientEntries != null) {
+ updateEntries(contactReceipientFilterResult.recipientEntries);
+ } else {
+ updateEntries(Collections.<RecipientEntry>emptyList());
+ }
}
}
private class RecipientEntryComparator implements Comparator<RecipientEntry> {
+
private final Collator mCollator;
public RecipientEntryComparator() {
@@ -272,6 +298,38 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
}
}
}
+
+ private class CursorResult {
+
+ public final Cursor personalCursor;
+
+ public Cursor enterpriseCursor;
+
+ public final boolean isSorted;
+
+ public CursorResult(Cursor personalCursor, boolean isSorted) {
+ this.personalCursor = personalCursor;
+ this.isSorted = isSorted;
+ }
+ }
+
+ private class ContactReceipientFilterResult {
+ /**
+ * Recipient entries in all directories.
+ */
+ public final List<RecipientEntry> recipientEntries;
+
+ /**
+ * Index of row that showing work directory header.
+ */
+ public final int workDirectoryPos;
+
+ public ContactReceipientFilterResult(List<RecipientEntry> recipientEntries,
+ int workDirectoryPos) {
+ this.recipientEntries = recipientEntries;
+ this.workDirectoryPos = workDirectoryPos;
+ }
+ }
}
/**
@@ -318,4 +376,81 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
// report matches
callback.matchesFound(recipientEntries);
}
+
+ /**
+ * We handle directory header here and then delegate the work of creating recipient views to
+ * the {@link BaseRecipientAdapter}. Please notice that we need to fix the position
+ * before passing to {@link BaseRecipientAdapter} because it is not aware of the existence of
+ * directory headers.
+ */
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView textView;
+ if (isDirectoryEntry(position)) {
+ if (convertView == null) {
+ textView = (TextView) mInflater.inflate(R.layout.work_directory_header, parent,
+ false);
+ } else {
+ textView = (TextView) convertView;
+ }
+ return textView;
+ }
+ return super.getView(fixPosition(position), convertView, parent);
+ }
+
+ @Override
+ public RecipientEntry getItem(int position) {
+ if (isDirectoryEntry(position)) {
+ return null;
+ }
+ return super.getItem(fixPosition(position));
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return RecipientEntry.ENTRY_TYPE_SIZE + 1;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ if (isDirectoryEntry(position)) {
+ return ENTRY_TYPE_DIRECTORY;
+ }
+ return super.getItemViewType(fixPosition(position));
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ if (isDirectoryEntry(position)) {
+ return false;
+ }
+ return super.isEnabled(fixPosition(position));
+ }
+
+ @Override
+ public int getCount() {
+ return super.getCount() + ((hasWorkDirectoryHeader()) ? 1 : 0);
+ }
+
+ private boolean isDirectoryEntry(int position) {
+ return position == mWorkDirectoryHeaderPos;
+ }
+
+ /**
+ * @return the position of items without counting directory headers.
+ */
+ private int fixPosition(int position) {
+ if (hasWorkDirectoryHeader()) {
+ Assert.isTrue(position != mWorkDirectoryHeaderPos);
+ if (position > mWorkDirectoryHeaderPos) {
+ return position - 1;
+ }
+ }
+ return position;
+ }
+
+ private boolean hasWorkDirectoryHeader() {
+ return mWorkDirectoryHeaderPos != WORD_DIRECTORY_HEADER_POS_NONE;
+ }
+
}