diff --git a/res/layout/expanding_entry_card_item.xml b/res/layout/expanding_entry_card_item.xml
index dbbeee5fa4a703e119844f2977db4ffb468c2aaa..c044428d57168df7c0123fbc4128da3e20f0022f 100644
--- a/res/layout/expanding_entry_card_item.xml
+++ b/res/layout/expanding_entry_card_item.xml
@@ -67,24 +67,29 @@
android:layout_marginEnd="@dimen/expanding_entry_card_item_sub_header_icon_margin_right"
android:layout_marginBottom="@dimen/expanding_entry_card_item_sub_header_icon_margin_bottom" />
-
-
-
+ android:orientation="horizontal"
+ android:gravity="center"
+ >
+
+
+
+
+
+
+
+
20dp
8dp
13dp
- 16dp
+ 13dp
27dp
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 525f29d365aad92a4002fa44cf31afcb754de6f9..026d298c6e07dfc767a92ea15eecd96079128fdd 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -102,6 +102,7 @@ import com.google.common.util.concurrent.Futures;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -138,6 +139,9 @@ public class PeopleActivity extends AppCompatContactsActivity implements
private static final String KEY_CONTACTS_VIEW = "contactsView";
private static final String KEY_NEW_GROUP_ACCOUNT = "newGroupAccount";
+ public static final String ACTION_OPEN_GROUP_FROM_CONTACT = "openGroupFromContact";
+ public static final String EXTRA_GROUP_ID = "groupId";
+
private static final long DRAWER_CLOSE_DELAY = 300L;
private ContactsIntentResolver mIntentResolver;
@@ -155,6 +159,8 @@ public class PeopleActivity extends AppCompatContactsActivity implements
private boolean mShouldSwitchToGroupView;
+ private boolean mGroupOpenedFromContact = false;
+
private ContactsView mCurrentView;
private CoordinatorLayout mLayoutRoot;
@@ -413,11 +419,33 @@ public class PeopleActivity extends AppCompatContactsActivity implements
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity.onCreate finish");
}
getWindow().setBackgroundDrawable(null);
+
+ openProvidedGroupFromContact(getIntent());
+ }
+
+ private void openProvidedGroupFromContact(Intent intent) {
+ if (intent == null) {
+ return;
+ }
+ final String action = intent.getAction();
+ if (Objects.equals(action, ACTION_OPEN_GROUP_FROM_CONTACT)) {
+ long groupId = intent.getLongExtra(EXTRA_GROUP_ID, -1);
+ if (groupId != -1) {
+ onGroupMenuItemClicked(groupId);
+ mGroupOpenedFromContact = true;
+ }
+ }
}
@Override
protected void onNewIntent(Intent intent) {
final String action = intent.getAction();
+
+ openProvidedGroupFromContact(intent);
+ if (isGroupOpenedFromContact()) {
+ return;
+ }
+
if (GroupUtil.ACTION_CREATE_GROUP.equals(action)) {
mGroupUri = intent.getData();
if (mGroupUri == null) {
@@ -794,6 +822,11 @@ public class PeopleActivity extends AppCompatContactsActivity implements
return;
}
+ if (isGroupOpenedFromContact()) {
+ finish();
+ return;
+ }
+
// Handle the back event in "second level".
if (isGroupView()) {
onBackPressedGroupView();
@@ -1238,6 +1271,10 @@ public class PeopleActivity extends AppCompatContactsActivity implements
return mCurrentView == ContactsView.GROUP_VIEW;
}
+ public boolean isGroupOpenedFromContact() {
+ return mGroupOpenedFromContact;
+ }
+
protected boolean isAssistantView() {
return mCurrentView == ContactsView.ASSISTANT;
}
diff --git a/src/com/android/contacts/model/GroupMembershipTools.java b/src/com/android/contacts/model/GroupMembershipTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d506b31c6e4de8cc78883861ec7d256245a0886
--- /dev/null
+++ b/src/com/android/contacts/model/GroupMembershipTools.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019-2023 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.android.contacts.model;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+
+public class GroupMembershipTools {
+
+ public boolean isTypeGroupMembership(String mimeType) {
+ return ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType);
+ }
+
+ public String getGroupTitle(Context context, long groupId) {
+ final Uri groupUri = ContactsContract.Groups.CONTENT_URI;
+
+ final String[] projection = new String[]{
+ ContactsContract.Groups._ID,
+ ContactsContract.Groups.TITLE,
+ };
+ final String selection = ContactsContract.Groups.AUTO_ADD + " = ? AND " + ContactsContract.Groups.FAVORITES + " = ?";
+ final String[] selectionArgs = new String[]{"0", "0"};
+
+ try {
+ Cursor groupCursor = context.getContentResolver().query(groupUri, projection, selection, selectionArgs, null, null);
+ if (groupCursor.moveToFirst()) {
+ do {
+ final int groupIdColumnIndex = groupCursor.getColumnIndex(ContactsContract.Groups._ID);
+ final int groupTitleColumnIndex = groupCursor.getColumnIndex(ContactsContract.Groups.TITLE);
+ if (groupIdColumnIndex == -1 || groupTitleColumnIndex == -1) {
+ groupCursor.close();
+ return null;
+ }
+ final long id = groupCursor.getLong(groupIdColumnIndex);
+ final String title = groupCursor.getString(groupTitleColumnIndex);
+ if (groupId == id) {
+ groupCursor.close();
+ return title;
+ }
+ } while (groupCursor.moveToNext());
+ }
+ groupCursor.close();
+ return null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index d462a0ee04a0cdf8128745abb8703cfb1b54b242..5ed14d8862541273b1bc5051cf0ca46e87447e60 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -617,6 +618,18 @@ public class ExpandingEntryCardView extends CardView {
thirdIcon.mutate();
thirdIcon.setColorFilter(mThemeColorFilter);
}
+ Drawable textIcon = entry.getTextIcon();
+ if (textIcon != null) {
+ textIcon.mutate();
+ if (entry.shouldApplyColor()) {
+ textIcon.setColorFilter(mThemeColorFilter);
+ } else {
+ final int textColor =
+ getResources().getColor(R.color.quickcontact_entry_sub_header_text_color);
+ textIcon.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP);
+ }
+ textIcon.setAlpha(200);
+ }
}
}
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 3983e4cc8bc5b112531eb962f1e8afba24d369f0..2fc193b20ab693708911aa001c6999fdd7a30672 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -109,6 +109,7 @@ import com.android.contacts.ShortcutIntentBuilder;
import com.android.contacts.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
import com.android.contacts.activities.ContactEditorActivity;
import com.android.contacts.activities.ContactSelectionActivity;
+import com.android.contacts.activities.PeopleActivity;
import com.android.contacts.activities.RequestPermissionsActivity;
import com.android.contacts.compat.CompatUtils;
import com.android.contacts.compat.EventCompat;
@@ -131,6 +132,7 @@ import com.android.contacts.logging.ScreenEvent.ScreenType;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.Contact;
import com.android.contacts.model.ContactLoader;
+import com.android.contacts.model.GroupMembershipTools;
import com.android.contacts.model.RawContact;
import com.android.contacts.model.account.AccountType;
import com.android.contacts.model.dataitem.CustomDataItem;
@@ -138,6 +140,7 @@ import com.android.contacts.model.dataitem.DataItem;
import com.android.contacts.model.dataitem.DataKind;
import com.android.contacts.model.dataitem.EmailDataItem;
import com.android.contacts.model.dataitem.EventDataItem;
+import com.android.contacts.model.dataitem.GroupMembershipDataItem;
import com.android.contacts.model.dataitem.ImDataItem;
import com.android.contacts.model.dataitem.NicknameDataItem;
import com.android.contacts.model.dataitem.NoteDataItem;
@@ -280,6 +283,7 @@ public class QuickContactActivity extends ContactsActivity {
private QuickContactImageView mPhotoView;
private ExpandingEntryCardView mContactCard;
+ private ExpandingEntryCardView mLabelsCard;
private ExpandingEntryCardView mNoContactDetailsCard;
private ExpandingEntryCardView mAboutCard;
@@ -336,7 +340,6 @@ public class QuickContactActivity extends ContactsActivity {
Event.CONTENT_ITEM_TYPE,
Relation.CONTENT_ITEM_TYPE,
Im.CONTENT_ITEM_TYPE,
- GroupMembership.CONTENT_ITEM_TYPE,
Identity.CONTENT_ITEM_TYPE,
CustomDataItem.MIMETYPE_CUSTOM_FIELD,
Note.CONTENT_ITEM_TYPE);
@@ -353,6 +356,8 @@ public class QuickContactActivity extends ContactsActivity {
private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment";
+ private static final GroupMembershipTools groupMembershipTools = new GroupMembershipTools();
+
final OnClickListener mEntryClickHandler = new OnClickListener() {
@Override
public void onClick(View v) {
@@ -699,6 +704,7 @@ public class QuickContactActivity extends ContactsActivity {
mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller);
mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card);
+ mLabelsCard = (ExpandingEntryCardView) findViewById(R.id.labels_card);
mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card);
mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card);
@@ -709,6 +715,9 @@ public class QuickContactActivity extends ContactsActivity {
mAboutCard.setOnClickListener(mEntryClickHandler);
mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
+ mLabelsCard.setOnClickListener(mEntryClickHandler);
+ mLabelsCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
+
mPhotoView = (QuickContactImageView) findViewById(R.id.photo);
final View transparentView = findViewById(R.id.transparent_view);
if (mScroller != null) {
@@ -1029,6 +1038,7 @@ public class QuickContactActivity extends ContactsActivity {
mOnlyOneEmail = emailDataItems != null && emailDataItems.size() == 1;
populateContactAndAboutCard(cp2DataCardModel, /* shouldAddPhoneticName */ true);
+ populateLabelsCard(mCachedCp2DataCardModel);
}
private void showActivity() {
@@ -1069,6 +1079,7 @@ public class QuickContactActivity extends ContactsActivity {
if (mHasIntentLaunched) {
mHasIntentLaunched = false;
populateContactAndAboutCard(mCachedCp2DataCardModel, /* shouldAddPhoneticName */ false);
+ populateLabelsCard(mCachedCp2DataCardModel);
}
maybeShowProgressDialog();
@@ -1180,6 +1191,31 @@ public class QuickContactActivity extends ContactsActivity {
Trace.endSection();
}
+ private void populateLabelsCard(Cp2DataCardModel cp2DataCardModel) {
+ mCachedCp2DataCardModel = cp2DataCardModel;
+ if (mHasIntentLaunched || cp2DataCardModel == null) {
+ return;
+ }
+
+ final List> labelEntries = cp2DataCardModel.labelEntries;
+ final String cardTitle = getString(R.string.groupsLabel);
+
+ mLabelsCard.setTitle(cardTitle);
+ mLabelsCard.initialize(labelEntries,
+ /* numInitialVisibleEntries = */ 1,
+ /* isExpanded = */ true,
+ /* isAlwaysExpanded = */ true,
+ mExpandingEntryCardViewListener,
+ mScroller);
+
+ if (labelEntries.size() > 0) {
+ mLabelsCard.setVisibility(View.VISIBLE);
+ return;
+ }
+
+ mLabelsCard.setVisibility(View.GONE);
+ }
+
/**
* Create a card that shows "Add email" and "Add phone number" entries in grey.
* When contact is a SIM contact, only shows "Add phone number".
@@ -1272,7 +1308,7 @@ public class QuickContactActivity extends ContactsActivity {
dataItem.setDataKind(dataKind);
final boolean hasData = !TextUtils.isEmpty(dataItem.buildDataString(this,
- dataKind));
+ dataKind)) || groupMembershipTools.isTypeGroupMembership(mimeType);
if (isMimeExcluded(mimeType) || !hasData) continue;
} else if (!tachyonEnabled) {
@@ -1300,8 +1336,17 @@ public class QuickContactActivity extends ContactsActivity {
*/
final List> dataItemsList = new ArrayList<>();
for (List mimeTypeDataItems : dataItemsMap.values()) {
- // Remove duplicate data items
- Collapser.collapseList(mimeTypeDataItems, this);
+ if (mimeTypeDataItems.isEmpty()) {
+ continue;
+ }
+
+ String mimeType = mimeTypeDataItems.get(0).getMimeType();
+
+ if (!groupMembershipTools.isTypeGroupMembership(mimeType)) {
+ // Remove duplicate data items
+ Collapser.collapseList(mimeTypeDataItems, this);
+ }
+
// Sort within mimetype
Collections.sort(mimeTypeDataItems, mWithinMimeTypeDataItemComparator);
// Add to the list of data item lists
@@ -1318,6 +1363,7 @@ public class QuickContactActivity extends ContactsActivity {
final List> contactCardEntries = new ArrayList<>();
final List> aboutCardEntries = buildAboutCardEntries(dataItemsMap);
+ final List> labelCardEntries = new ArrayList<>();
final MutableString aboutCardName = new MutableString();
for (int i = 0; i < dataItemsList.size(); ++i) {
@@ -1326,6 +1372,12 @@ public class QuickContactActivity extends ContactsActivity {
if (SORTED_ABOUT_CARD_MIMETYPES.contains(topDataItem.getMimeType())) {
// About card mimetypes are built in buildAboutCardEntries, skip here
continue;
+ } else if (groupMembershipTools.isTypeGroupMembership(topDataItem.getMimeType())) {
+ List labelEntries = dataItemsToEntries(dataItemsByMimeType,
+ aboutCardName);
+ if (labelEntries.size() > 0) {
+ labelCardEntries.add(labelEntries);
+ }
} else {
List contactEntries = dataItemsToEntries(dataItemsList.get(i),
aboutCardName);
@@ -1341,6 +1393,7 @@ public class QuickContactActivity extends ContactsActivity {
dataModel.customAboutCardName = aboutCardName.value;
dataModel.aboutCardEntries = aboutCardEntries;
dataModel.contactCardEntries = contactCardEntries;
+ dataModel.labelEntries = labelCardEntries;
dataModel.dataItemsMap = dataItemsMap;
dataModel.areAllRawContactsSimAccounts = data.areAllRawContactsSimAccounts(this);
return dataModel;
@@ -1380,6 +1433,7 @@ public class QuickContactActivity extends ContactsActivity {
public Map> dataItemsMap;
public List> aboutCardEntries;
public List> contactCardEntries;
+ public List> labelEntries;
public String customAboutCardName;
public boolean areAllRawContactsSimAccounts;
}
@@ -1717,6 +1771,24 @@ public class QuickContactActivity extends ContactsActivity {
aboutCardName.value = res.getString(R.string.about_card_title);
}
}
+ } else if (dataItem instanceof GroupMembershipDataItem) {
+
+ final GroupMembershipDataItem group = (GroupMembershipDataItem) dataItem;
+ String groupTitle = groupMembershipTools.getGroupTitle(context, group.getGroupRowId());
+
+ if (!TextUtils.isEmpty(groupTitle)) {
+ text = groupTitle;
+ textIcon = res.getDrawable(R.drawable.quantum_ic_label_vd_theme_24);
+
+ entryContextMenuInfo = new EntryContextMenuInfo(text,
+ res.getString(R.string.groupsLabel), dataItem.getMimeType(),
+ dataItem.getId(), dataItem.isSuperPrimary());
+
+ intent = new Intent(context, PeopleActivity.class)
+ .setAction(PeopleActivity.ACTION_OPEN_GROUP_FROM_CONTACT)
+ .putExtra(PeopleActivity.EXTRA_GROUP_ID, group.getGroupRowId());
+ }
+
} else if (CallUtil.isTachyonEnabled(context) && MIMETYPE_TACHYON.equals(
dataItem.getMimeType())) {
// Skip these actions. They will be placed by the phone number.
@@ -2057,6 +2129,7 @@ public class QuickContactActivity extends ContactsActivity {
new PorterDuffColorFilter(mColorFilterColor, PorterDuff.Mode.SRC_ATOP);
mContactCard.setColorAndFilter(mColorFilterColor, mColorFilter);
mAboutCard.setColorAndFilter(mColorFilterColor, mColorFilter);
+ mLabelsCard.setColorAndFilter(mColorFilterColor, mColorFilter);
}
private void updateStatusBarColor() {