Add suggestion card for quick contact (P2)
Add a card for suggestion in quick contact, showing the
aggregation suggestions for the contact and supply merge option.
BUG 21071527
Change-Id: I7abe28c8a5fb3aac47607153f3d962271387713a
diff --git a/res/layout/quickcontact_content.xml b/res/layout/quickcontact_content.xml
index 494b93b..9c4e644 100644
--- a/res/layout/quickcontact_content.xml
+++ b/res/layout/quickcontact_content.xml
@@ -54,6 +54,8 @@
android:visibility="gone"
cardview:cardCornerRadius="@dimen/expanding_entry_card_card_corner_radius" />
+ <include layout="@layout/quickcontact_suggestion_card" />
+
</LinearLayout>
</com.android.contacts.widget.TouchlessScrollView>
\ No newline at end of file
diff --git a/res/layout/quickcontact_suggestion_card.xml b/res/layout/quickcontact_suggestion_card.xml
new file mode 100644
index 0000000..45e316b
--- /dev/null
+++ b/res/layout/quickcontact_suggestion_card.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<!--
+ Layout for the suggestion card in QuickContact.
+-->
+<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ style="@style/ExpandingEntryCardStyle"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:visibility="gone"
+ android:id="@+id/suggestion_card_view">
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="@dimen/quickcontact_suggestion_card_layout_margin"
+ android:layout_marginBottom="@dimen/quickcontact_suggestion_card_layout_margin"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/suggestion_icon"
+ android:layout_width="@dimen/quickcontact_suggestion_card_icon_height"
+ android:layout_height="@dimen/quickcontact_suggestion_card_icon_width"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/quickcontact_suggestion_card_image_spacing"
+ android:scaleType="fitCenter" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:layout_toEndOf="@+id/line_vertical_separator"
+ android:layout_marginStart="@dimen/expanding_entry_card_item_image_spacing"
+ android:layout_marginEnd="@dimen/expanding_entry_card_item_image_spacing">
+
+ <TextView
+ android:id="@+id/suggestion_for_name"
+ android:textSize="@dimen/expanding_entry_card_title_text_size"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@color/quickcontact_entry_header_text_color"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"/>
+
+ <TextView
+ android:id="@+id/suggestion_number"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="viewStart"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@color/quickcontact_entry_sub_header_text_color" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/suggestion_summary"
+ android:textAlignment="viewStart"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@color/quickcontact_entry_sub_header_text_color" />
+ </LinearLayout>
+
+ <View
+ android:id="@+id/line_vertical_separator"
+ android:layout_width="@dimen/divider_line_height"
+ android:layout_height="match_parent"
+ android:layout_toEndOf="@+id/expand_suggestion_button"
+ android:background="@color/divider_line_color_light"/>
+
+ <ImageView
+ android:id="@+id/expand_suggestion_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|end"
+ android:layout_alignParentEnd="true"
+ android:paddingStart="@dimen/editor_round_button_padding_left"
+ android:paddingEnd="@dimen/editor_round_button_padding_right"
+ android:paddingTop="@dimen/editor_round_button_padding_top"
+ android:paddingBottom="@dimen/editor_round_button_padding_bottom"/>
+
+ </LinearLayout>
+
+ <View
+ android:id="@+id/title_separator"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/divider_line_height"
+ android:paddingTop="@dimen/editor_round_button_padding_top"
+ android:background="@color/divider_line_color_light"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/suggestion_list"
+ android:animateLayoutChanges="true"
+ android:orientation="vertical" />
+
+ <View
+ android:id="@+id/title_separator2"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/divider_line_height"
+ android:background="@color/divider_line_color_light"
+ android:visibility="gone"/>
+
+ <Button
+ android:id="@+id/merge_button"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/quickcontact_suggestion_merge_button"
+ android:textColor="@color/quickcontact_entry_sub_header_text_color"
+ android:paddingStart="@dimen/quickcontact_suggestion_card_image_spacing"/>
+ </LinearLayout>
+</android.support.v7.widget.CardView>
\ No newline at end of file
diff --git a/res/layout/quickcontact_suggestion_contact_item.xml b/res/layout/quickcontact_suggestion_contact_item.xml
new file mode 100644
index 0000000..76792f8
--- /dev/null
+++ b/res/layout/quickcontact_suggestion_contact_item.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/quickcontact_suggestion_card_layout_margin"
+ android:layout_marginBottom="@dimen/quickcontact_suggestion_card_layout_margin">
+
+ <ImageView
+ android:id="@+id/aggregation_suggestion_photo"
+ android:layout_width="@dimen/quickcontact_suggestion_card_icon_height"
+ android:layout_height="@dimen/quickcontact_suggestion_card_icon_width"
+ android:layout_marginStart="@dimen/quickcontact_suggestion_card_image_spacing"
+ android:scaleType="fitCenter"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/expanding_entry_card_item_image_spacing"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical">
+
+ <TextView
+ android:id="@+id/aggregation_suggestion_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/expanding_entry_card_title_text_size"
+ android:textColor="@color/quickcontact_entry_sub_header_text_color"
+ android:layout_marginTop="@dimen/quickcontact_suggestion_card_layout_margin"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/aggregation_suggestion_account_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_marginBottom="@dimen/quickcontact_suggestion_card_layout_margin"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@color/quickcontact_entry_sub_header_text_color" />
+
+ </LinearLayout>
+
+ <CheckBox
+ android:id="@+id/suggestion_checkbox"
+ android:layout_gravity="center_vertical|end"
+ android:layout_alignParentEnd="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:shadowColor="@color/divider_line_color_light"
+ android:layout_marginEnd="@dimen/quickcontact_suggestion_card_checkbox_right_margin"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c57127f..a5187d2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -228,6 +228,12 @@
<dimen name="expanding_entry_card_item_header_only_margin_bottom">2dp</dimen>
<dimen name="expanding_entry_card_item_no_icon_margin_top">6dp</dimen>
+ <dimen name="quickcontact_suggestion_card_icon_height">24dp</dimen>
+ <dimen name="quickcontact_suggestion_card_icon_width">24dp</dimen>
+ <dimen name="quickcontact_suggestion_card_image_spacing">20dp</dimen>
+ <dimen name="quickcontact_suggestion_card_layout_margin">8dp</dimen>
+ <dimen name="quickcontact_suggestion_card_checkbox_right_margin">16dp</dimen>
+
<!-- The width the that the tabs occupy in the ActionBar when in landscape mode.
426dp is the height of a "small" screen. We should leave 240dp for
the title and menu items -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d992e81..d4979f4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -770,4 +770,22 @@
<!-- Quick contact display name with phonetic name -->
<string name="quick_contact_display_name_with_phonetic"><xliff:g id="display_name">%s</xliff:g> (<xliff:g id="phonetic_name">%s</xliff:g>)</string>
+
+ <!-- Button used in quick contact suggestion card to merge selected contacts. [CHAR LIMIT=30]-->
+ <string name="quickcontact_suggestion_merge_button">Merge</string>
+
+ <!-- Suggestions number in quick contact suggestion card [CHAR LIMIT=30] -->
+ <plurals name="quickcontact_suggestions_number">
+ <item quantity="one">1 suggested contact</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> suggested contacts</item>
+ </plurals>
+
+ <!-- Account type number for suggestions in quick contact suggestion card [CHAR LIMIT=30]-->
+ <plurals name="quickcontact_suggestion_account_type_number">
+ <item quantity="one"></item>
+ <item quantity="other">(<xliff:g id="count">%d</xliff:g>)</item>
+ </plurals>
+
+ <!-- Account type with number in quick contact suggestion card [CHAR LIMIT=30]-->
+ <string name="quickcontact_suggestion_account_type"><xliff:g id="account_type">%s</xliff:g><xliff:g id="account_type_number">%s</xliff:g></string>
</resources>
diff --git a/src/com/android/contacts/editor/AggregationSuggestionEngine.java b/src/com/android/contacts/editor/AggregationSuggestionEngine.java
index ed4f313..14da019 100644
--- a/src/com/android/contacts/editor/AggregationSuggestionEngine.java
+++ b/src/com/android/contacts/editor/AggregationSuggestionEngine.java
@@ -103,8 +103,6 @@
private static final long SUGGESTION_LOOKUP_DELAY_MILLIS = 300;
- private static final int MAX_SUGGESTION_COUNT = 3;
-
private final Context mContext;
private long[] mSuggestedContactIds = new long[0];
@@ -116,6 +114,7 @@
private Cursor mDataCursor;
private ContentObserver mContentObserver;
private Uri mSuggestionsUri;
+ private int mSuggestionsLimit = 3;
public AggregationSuggestionEngine(Context context) {
super("AggregationSuggestions", Process.THREAD_PRIORITY_BACKGROUND);
@@ -147,6 +146,10 @@
}
}
+ public void setSuggestionsLimit(int suggestionsLimit) {
+ mSuggestionsLimit = suggestionsLimit;
+ }
+
public void setListener(Listener listener) {
mListener = listener;
}
@@ -219,7 +222,7 @@
}
Builder builder = new AggregationSuggestions.Builder()
- .setLimit(MAX_SUGGESTION_COUNT)
+ .setLimit(mSuggestionsLimit)
.setContactId(mContactId);
if (nameSb.length() != 0) {
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 8bb6976..c89c5f4 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -45,6 +45,7 @@
import android.os.Bundle;
import android.os.Trace;
import android.provider.CalendarContract;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
@@ -67,6 +68,7 @@
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsContract.RawContacts;
import android.support.v7.graphics.Palette;
+import android.support.v7.widget.CardView;
import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import android.text.BidiFormatter;
@@ -76,6 +78,7 @@
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -84,6 +87,11 @@
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -94,6 +102,7 @@
import com.android.contacts.common.CallUtil;
import com.android.contacts.common.ClipboardUtils;
import com.android.contacts.common.Collapser;
+import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.activity.RequestPermissionsActivity;
import com.android.contacts.common.dialog.CallSubjectDialog;
@@ -122,6 +131,7 @@
import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
import com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
import com.android.contacts.common.model.dataitem.WebsiteDataItem;
+import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.common.util.DateUtils;
import com.android.contacts.common.util.MaterialColorMapUtils;
@@ -129,12 +139,15 @@
import com.android.contacts.common.util.UriUtils;
import com.android.contacts.common.util.ViewUtil;
import com.android.contacts.detail.ContactDisplayUtils;
+import com.android.contacts.editor.AggregationSuggestionEngine;
+import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
import com.android.contacts.editor.ContactEditorFragment;
import com.android.contacts.editor.EditorIntents;
import com.android.contacts.interactions.CalendarInteractionsLoader;
import com.android.contacts.interactions.CallLogInteractionsLoader;
import com.android.contacts.interactions.ContactDeletionInteraction;
import com.android.contacts.interactions.ContactInteraction;
+import com.android.contacts.interactions.JoinContactsDialogFragment;
import com.android.contacts.interactions.SmsInteractionsLoader;
import com.android.contacts.quickcontact.ExpandingEntryCardView.Entry;
import com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo;
@@ -160,8 +173,11 @@
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -169,7 +185,8 @@
* data asynchronously, and then shows a popup with details centered around
* {@link Intent#getSourceBounds()}.
*/
-public class QuickContactActivity extends ContactsActivity {
+public class QuickContactActivity extends ContactsActivity
+ implements AggregationSuggestionEngine.Listener {
/**
* QuickContacts immediately takes up the full screen. All possible information is shown.
@@ -181,6 +198,8 @@
private static final String TAG = "QuickContact";
private static final String KEY_THEME_COLOR = "theme_color";
+ private static final String KEY_IS_SUGGESTION_LIST_COLLAPSED = "is_suggestion_list_collapsed";
+ private static final String KEY_SELECTED_SUGGESTION_CONTACTS = "selected_suggestion_contacts";
private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150;
private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1;
@@ -224,10 +243,28 @@
private ExpandingEntryCardView mNoContactDetailsCard;
private ExpandingEntryCardView mRecentCard;
private ExpandingEntryCardView mAboutCard;
+
+ // Suggestion card.
+ private CardView mSuggestionCardView;
+ private ImageView mSuggestionSummaryPhoto;
+ private TextView mSuggestionForName;
+ private TextView mSuggestionNumber;
+ private TextView mSuggestionSummary;
+ private ImageView mSuggestionExpansionButton;
+ private LinearLayout mSuggestionList;
+ private View mSuggestionSeparator;
+ private Button mSuggestionsMergeButton;
+ private boolean mIsSuggestionListCollapsed;
+
private MultiShrinkScroller mScroller;
private SelectAccountDialogFragmentListener mSelectAccountFragmentListener;
private AsyncTask<Void, Void, Cp2DataCardModel> mEntriesAndActionsTask;
private AsyncTask<Void, Void, Void> mRecentDataTask;
+
+ private AggregationSuggestionEngine mAggregationSuggestionEngine;
+ private List<Suggestion> mSuggestions;
+
+ private TreeSet<Long> mSelectedAggregationIds = new TreeSet<>();
/**
* The last copy of Cp2DataCardModel that was passed to {@link #populateContactAndAboutCard}.
*/
@@ -442,6 +479,154 @@
}
};
+ @Override
+ public void onAggregationSuggestionChange() {
+ mSuggestions = mAggregationSuggestionEngine.getSuggestions();
+ mSuggestionCardView.setVisibility(View.GONE);
+ mSuggestionList.removeAllViews();
+
+ final String suggestionForName = mContactData.getDisplayName();
+ final int suggestionNumber = mSuggestions.size();
+ final String suggestionSummary = getSuggestionAccountSummary(mSuggestions);
+
+ if (suggestionNumber > 0) {
+ mSuggestionCardView.setVisibility(View.VISIBLE);
+
+ // Take the first suggestion 's photo as the summary photo.
+ // TODO: take all suggestions' photos.
+ final Suggestion firstSuggestion = mSuggestions.get(0);
+ if (firstSuggestion.photo != null) {
+ mSuggestionSummaryPhoto.setImageBitmap(BitmapFactory.decodeByteArray(
+ firstSuggestion.photo, 0, firstSuggestion.photo.length));
+ } else {
+ mSuggestionSummaryPhoto.setImageDrawable(
+ ContactPhotoManager.getDefaultAvatarDrawableForContact(
+ getResources(), false, null));
+ }
+
+ mSuggestionForName.setText(suggestionForName);
+ mSuggestionNumber.setText(getResources().getQuantityString(
+ R.plurals.quickcontact_suggestions_number, suggestionNumber, suggestionNumber));
+ mSuggestionSummary.setText(suggestionSummary);
+
+ for (Suggestion suggestion : mSuggestions) {
+ mSuggestionList.addView(inflateSuggestionListView(suggestion));
+ }
+
+ mSuggestionExpansionButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mIsSuggestionListCollapsed) {
+ expandSuggestionList();
+ } else {
+ collapseSuggestionList();
+ }
+ }
+ });
+
+ } else {
+ mSuggestionCardView.setVisibility(View.GONE);
+ }
+ }
+
+ private void collapseSuggestionList() {
+ mSuggestionList.setVisibility(View.GONE);
+ mSuggestionSeparator.setVisibility(View.GONE);
+ mSuggestionExpansionButton.setImageResource(
+ R.drawable.ic_menu_expander_minimized_holo_light);
+ mIsSuggestionListCollapsed = true;
+ }
+
+ private void expandSuggestionList() {
+ mSuggestionList.setVisibility(View.VISIBLE);
+ mSuggestionSeparator.setVisibility(View.VISIBLE);
+ mSuggestionExpansionButton.setImageResource(
+ R.drawable.ic_menu_expander_maximized_holo_light);
+ mIsSuggestionListCollapsed = false;
+ }
+ /**
+ * Return summary like "Google(2),LinkedIn" for 3 suggestions.
+ */
+ private String getSuggestionAccountSummary(List<Suggestion> suggestions) {
+ Map<String, Integer> accountTypeMap = new HashMap<String, Integer>();
+ for (Suggestion suggestion : suggestions) {
+ final com.android.contacts.editor.AggregationSuggestionEngine.RawContact rawContact =
+ suggestion.rawContacts.get(0);
+ final String displayAccountType = getDisplayAccountType(
+ rawContact.accountType, rawContact.dataSet);
+ if (accountTypeMap.containsKey(displayAccountType)) {
+ int count = accountTypeMap.get(displayAccountType);
+ count++;
+ accountTypeMap.put(displayAccountType, count);
+ } else {
+ accountTypeMap.put(displayAccountType, 1);
+ }
+ }
+
+ Set<String> accountTypeWithNumber = new HashSet<>();
+ for (String accountType : accountTypeMap.keySet()) {
+ final String number = getResources().getQuantityString(
+ R.plurals.quickcontact_suggestion_account_type_number,
+ accountTypeMap.get(accountType),
+ accountTypeMap.get(accountType));
+ accountTypeWithNumber.add(getResources().getString(
+ R.string.quickcontact_suggestion_account_type, accountType, number));
+ }
+ return TextUtils.join(",", accountTypeWithNumber);
+ }
+
+ private String getDisplayAccountType(String accountTypeString, String dataSet) {
+ final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(this);
+ final AccountType accountType = accountTypeManager.getAccountType(
+ accountTypeString, dataSet);
+ return accountType.getDisplayLabel(this).toString();
+ }
+
+ private View inflateSuggestionListView(Suggestion suggestion) {
+ final LayoutInflater layoutInflater = LayoutInflater.from(this);
+ final View suggestionView = layoutInflater.inflate(
+ R.layout.quickcontact_suggestion_contact_item, null);
+
+ final ImageView photo = (ImageView) suggestionView.findViewById(
+ R.id.aggregation_suggestion_photo);
+ if (suggestion.photo != null) {
+ photo.setImageBitmap(BitmapFactory.decodeByteArray(
+ suggestion.photo, 0, suggestion.photo.length));
+ } else {
+ photo.setImageDrawable(ContactPhotoManager.getDefaultAvatarDrawableForContact(
+ getResources(), false, null));
+ }
+
+ final TextView name = (TextView) suggestionView.findViewById(R.id.aggregation_suggestion_name);
+ name.setText(suggestion.name);
+
+ final TextView accountTypeView = (TextView) suggestionView.findViewById(
+ R.id.aggregation_suggestion_account_type);
+ final String accountTypeString = suggestion.rawContacts.get(0).accountType;
+ final String dataSet = suggestion.rawContacts.get(0).dataSet;
+ final String displayAccountType = getDisplayAccountType(accountTypeString, dataSet);
+ if (!TextUtils.isEmpty(displayAccountType)) {
+ accountTypeView.setText(displayAccountType);
+ }
+
+ final CheckBox checkbox = (CheckBox) suggestionView.findViewById(R.id.suggestion_checkbox);
+ checkbox.setChecked(mSelectedAggregationIds.contains(suggestion.contactId));
+ checkbox.setTag(suggestion.contactId);
+ checkbox.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final CheckBox checkBox = (CheckBox) v;
+ final Long contactId = (Long) checkBox.getTag();
+ if (checkBox.isChecked()) {
+ mSelectedAggregationIds.add(contactId);
+ } else {
+ mSelectedAggregationIds.remove(contactId);
+ }
+ }
+ });
+ return suggestionView;
+ }
+
private interface ContextMenuIds {
static final int COPY_TEXT = 0;
static final int CLEAR_DEFAULT = 1;
@@ -715,6 +900,39 @@
mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card);
mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card);
+ mSuggestionCardView = (CardView) findViewById(R.id.suggestion_card_view);
+ mSuggestionSummaryPhoto = (ImageView) findViewById(R.id.suggestion_icon);
+ mSuggestionForName = (TextView) findViewById(R.id.suggestion_for_name);
+ mSuggestionNumber = (TextView) findViewById(R.id.suggestion_number);
+ mSuggestionSummary = (TextView) findViewById(R.id.suggestion_summary);
+ mSuggestionExpansionButton = (ImageView) findViewById(R.id.expand_suggestion_button);
+ mSuggestionSeparator = findViewById(R.id.title_separator2);
+ mSuggestionList = (LinearLayout) findViewById(R.id.suggestion_list);
+ mSuggestionsMergeButton = (Button) findViewById(R.id.merge_button);
+ if (savedInstanceState != null) {
+ mIsSuggestionListCollapsed = savedInstanceState.getBoolean(
+ KEY_IS_SUGGESTION_LIST_COLLAPSED, true);
+ mSelectedAggregationIds = (TreeSet<Long>)
+ savedInstanceState.getSerializable(KEY_SELECTED_SUGGESTION_CONTACTS);
+ } else {
+ mIsSuggestionListCollapsed = true;
+ mSelectedAggregationIds.clear();
+ }
+
+ mSuggestionExpansionButton.setClickable(true);
+ mSuggestionsMergeButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // Join selected contacts.
+ if (!mSelectedAggregationIds.contains(mContactData.getId())) {
+ mSelectedAggregationIds.add(mContactData.getId());
+ }
+ TreeSet<Long> mergedContactIds = new TreeSet<Long>(mSelectedAggregationIds);
+ mSelectedAggregationIds.clear(); // Clear selected ids for merged contact.
+ JoinContactsDialogFragment.start(QuickContactActivity.this, mergedContactIds);
+ }
+ });
+
mNoContactDetailsCard.setOnClickListener(mEntryClickHandler);
mContactCard.setOnClickListener(mEntryClickHandler);
mContactCard.setExpandButtonText(
@@ -844,6 +1062,9 @@
if (mColorFilter != null) {
savedInstanceState.putInt(KEY_THEME_COLOR, mColorFilterColor);
}
+ savedInstanceState.putBoolean(KEY_IS_SUGGESTION_LIST_COLLAPSED, mIsSuggestionListCollapsed);
+ savedInstanceState.putSerializable(
+ KEY_SELECTED_SUGGESTION_CONTACTS, mSelectedAggregationIds);
}
private void processIntent(Intent intent) {
@@ -982,6 +1203,7 @@
private void bindDataToCards(Cp2DataCardModel cp2DataCardModel) {
startInteractionLoaders(cp2DataCardModel);
populateContactAndAboutCard(cp2DataCardModel);
+ populateSuggestionCard();
}
private void startInteractionLoaders(Cp2DataCardModel cp2DataCardModel) {
@@ -1085,6 +1307,34 @@
}
}
+ private void populateSuggestionCard() {
+ // Initialize suggestion related view and data.
+ if (mIsSuggestionListCollapsed) {
+ collapseSuggestionList();
+ } else {
+ expandSuggestionList();
+ }
+ mSuggestionCardView.setVisibility(View.GONE);
+ mSuggestionList.removeAllViews();
+
+ if (mAggregationSuggestionEngine == null) {
+ mAggregationSuggestionEngine = new AggregationSuggestionEngine(this);
+ mAggregationSuggestionEngine.setListener(this);
+ mAggregationSuggestionEngine.setSuggestionsLimit(10);
+ mAggregationSuggestionEngine.start();
+ }
+
+ mAggregationSuggestionEngine.setContactId(mContactData.getId());
+
+ // Trigger suggestion engine to compute suggestions.
+ final ContentValues values = new ContentValues();
+ values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
+ mContactData.getDisplayName());
+ values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME,
+ mContactData.getPhoneticName());
+ mAggregationSuggestionEngine.onNameChange(ValuesDelta.fromBefore(values));
+ }
+
private void populateContactAndAboutCard(Cp2DataCardModel cp2DataCardModel) {
mCachedCp2DataCardModel = cp2DataCardModel;
if (mHasIntentLaunched || cp2DataCardModel == null) {
@@ -2248,6 +2498,14 @@
}
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mAggregationSuggestionEngine != null) {
+ mAggregationSuggestionEngine.quit();
+ }
+ }
+
/**
* Returns true if it is possible to edit the current contact.
*/