diff options
| author | 2021-03-23 16:42:53 +0000 | |
|---|---|---|
| committer | 2021-03-23 16:42:53 +0000 | |
| commit | 5785c5c68f52f85f06f5d4ecb39a2498b254362c (patch) | |
| tree | 6befc935281ed7615ade155cefb5d470e7f053df | |
| parent | 2c691e8dc2a529f9e70f8883c3d4dcd6dc14d58e (diff) | |
| parent | 87eec50482141da49ac77ec1f9057af65acdd42b (diff) | |
Merge "Show messages count in People Tile" into sc-dev
11 files changed, 157 insertions, 16 deletions
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java index dd2ba7db03ae..e645831a31b1 100644 --- a/core/java/android/app/people/PeopleSpaceTile.java +++ b/core/java/android/app/people/PeopleSpaceTile.java @@ -56,6 +56,7 @@ public class PeopleSpaceTile implements Parcelable { private CharSequence mNotificationContent; private String mNotificationCategory; private Uri mNotificationDataUri; + private int mMessagesCount; private Intent mIntent; private long mNotificationTimestamp; private List<ConversationStatus> mStatuses; @@ -74,6 +75,7 @@ public class PeopleSpaceTile implements Parcelable { mNotificationContent = b.mNotificationContent; mNotificationCategory = b.mNotificationCategory; mNotificationDataUri = b.mNotificationDataUri; + mMessagesCount = b.mMessagesCount; mIntent = b.mIntent; mNotificationTimestamp = b.mNotificationTimestamp; mStatuses = b.mStatuses; @@ -140,6 +142,10 @@ public class PeopleSpaceTile implements Parcelable { return mNotificationDataUri; } + public int getMessagesCount() { + return mMessagesCount; + } + /** * Provides an intent to launch. If present, we should manually launch the intent on tile * click, rather than calling {@link android.content.pm.LauncherApps} to launch the shortcut ID. @@ -175,6 +181,7 @@ public class PeopleSpaceTile implements Parcelable { builder.setNotificationContent(mNotificationContent); builder.setNotificationCategory(mNotificationCategory); builder.setNotificationDataUri(mNotificationDataUri); + builder.setMessagesCount(mMessagesCount); builder.setIntent(mIntent); builder.setNotificationTimestamp(mNotificationTimestamp); builder.setStatuses(mStatuses); @@ -196,6 +203,7 @@ public class PeopleSpaceTile implements Parcelable { private CharSequence mNotificationContent; private String mNotificationCategory; private Uri mNotificationDataUri; + private int mMessagesCount; private Intent mIntent; private long mNotificationTimestamp; private List<ConversationStatus> mStatuses; @@ -320,6 +328,12 @@ public class PeopleSpaceTile implements Parcelable { return this; } + /** Sets the number of messages associated with the Tile. */ + public Builder setMessagesCount(int messagesCount) { + mMessagesCount = messagesCount; + return this; + } + /** Sets an intent to launch on click. */ public Builder setIntent(Intent intent) { mIntent = intent; @@ -359,6 +373,7 @@ public class PeopleSpaceTile implements Parcelable { mNotificationContent = in.readCharSequence(); mNotificationCategory = in.readString(); mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader()); + mMessagesCount = in.readInt(); mIntent = in.readParcelable(Intent.class.getClassLoader()); mNotificationTimestamp = in.readLong(); mStatuses = new ArrayList<>(); @@ -385,6 +400,7 @@ public class PeopleSpaceTile implements Parcelable { dest.writeCharSequence(mNotificationContent); dest.writeString(mNotificationCategory); dest.writeParcelable(mNotificationDataUri, flags); + dest.writeInt(mMessagesCount); dest.writeParcelable(mIntent, flags); dest.writeLong(mNotificationTimestamp); dest.writeParcelableList(mStatuses, flags); diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java index 7cb680499d98..36da927116b7 100644 --- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java +++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java @@ -235,6 +235,7 @@ public class PeopleSpaceTileTest { .setStatuses(statusList).setNotificationKey("key") .setNotificationContent("content") .setNotificationDataUri(Uri.parse("data")) + .setMessagesCount(2) .setIntent(new Intent()) .build(); @@ -256,6 +257,7 @@ public class PeopleSpaceTileTest { assertThat(readTile.getNotificationKey()).isEqualTo(tile.getNotificationKey()); assertThat(readTile.getNotificationContent()).isEqualTo(tile.getNotificationContent()); assertThat(readTile.getNotificationDataUri()).isEqualTo(tile.getNotificationDataUri()); + assertThat(readTile.getMessagesCount()).isEqualTo(tile.getMessagesCount()); assertThat(readTile.getIntent().toString()).isEqualTo(tile.getIntent().toString()); } @@ -291,6 +293,17 @@ public class PeopleSpaceTileTest { } @Test + public void testMessagesCount() { + PeopleSpaceTile tile = + new PeopleSpaceTile.Builder(new ShortcutInfo.Builder(mContext, "123").build(), + mLauncherApps) + .setMessagesCount(2) + .build(); + + assertThat(tile.getMessagesCount()).isEqualTo(2); + } + + @Test public void testIntent() { PeopleSpaceTile tile = new PeopleSpaceTile.Builder( new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build(); diff --git a/packages/SystemUI/res/drawable/people_space_messages_count_background.xml b/packages/SystemUI/res/drawable/people_space_messages_count_background.xml new file mode 100644 index 000000000000..0fc112e16ee4 --- /dev/null +++ b/packages/SystemUI/res/drawable/people_space_messages_count_background.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" > + <solid android:color="#9ED582" /> + <corners android:radius="@dimen/people_space_messages_count_radius" /> +</shape> diff --git a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml index e4e4cd8956a7..db1d46d2117a 100644 --- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml +++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml @@ -98,8 +98,8 @@ android:orientation="horizontal" android:paddingTop="4dp" android:layout_width="match_parent" - android:layout_height="wrap_content"> - + android:layout_height="wrap_content" + android:clipToOutline="true"> <TextView android:id="@+id/name" android:gravity="center_vertical" @@ -112,7 +112,21 @@ android:ellipsize="end" android:layout_width="wrap_content" android:layout_height="wrap_content" /> - + <TextView + android:id="@+id/messages_count" + android:gravity="end" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem" + android:textColor="?android:attr/textColorPrimary" + android:background="@drawable/people_space_messages_count_background" + android:textSize="14sp" + android:maxLines="1" + android:ellipsize="end" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + /> <ImageView android:id="@+id/predefined_icon" android:gravity="end|center_vertical" diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index ff4e8e002d88..2393b749b64e 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1353,6 +1353,7 @@ <dimen name="people_space_widget_radius">28dp</dimen> <dimen name="people_space_image_radius">20dp</dimen> + <dimen name="people_space_messages_count_radius">12dp</dimen> <dimen name="people_space_widget_background_padding">6dp</dimen> <dimen name="required_width_for_medium">146dp</dimen> <dimen name="required_width_for_large">138dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 691d111089b8..94bf86ab07da 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2865,6 +2865,8 @@ <string name="empty_status">Let’s chat tonight!</string> <!-- Default text for missed call notifications on their Conversation widget [CHAR LIMIT=20] --> <string name="missed_call">Missed call</string> + <!-- Text when a Notification may have more messages than the number indicated [CHAR LIMIT=5] --> + <string name="messages_count_overflow_indicator"><xliff:g id="number" example="7">%d</xliff:g>+</string> <!-- Description text for adding a Conversation widget [CHAR LIMIT=100] --> <string name="people_tile_description">See recent messages, missed calls, and status updates</string> <!-- Title text displayed for the Conversation widget [CHAR LIMIT=50] --> diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java index 93ce5a83f684..5bc128062adc 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java @@ -274,13 +274,17 @@ public class PeopleSpaceUtils { return tile; } boolean isMissedCall = Objects.equals(notification.category, CATEGORY_MISSED_CALL); - Notification.MessagingStyle.Message message = getLastMessagingStyleMessage(notification); + List<Notification.MessagingStyle.Message> messages = + getMessagingStyleMessages(notification); - if (!isMissedCall && message == null) { + if (!isMissedCall && ArrayUtils.isEmpty(messages)) { if (DEBUG) Log.d(TAG, "Notification has no content"); return tile; } + // messages are in chronological order from most recent to least. + Notification.MessagingStyle.Message message = messages != null ? messages.get(0) : null; + int messagesCount = messages != null ? messages.size() : 0; // If it's a missed call notification and it doesn't include content, use fallback value, // otherwise, use notification content. boolean hasMessageText = message != null && !TextUtils.isEmpty(message.getText()); @@ -294,12 +298,16 @@ public class PeopleSpaceUtils { .setNotificationCategory(notification.category) .setNotificationContent(content) .setNotificationDataUri(dataUri) + .setMessagesCount(messagesCount) .build(); } - /** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */ + /** + * Returns {@link Notification.MessagingStyle.Message}s from the Notification in chronological + * order from most recent to least. + */ @VisibleForTesting - public static Notification.MessagingStyle.Message getLastMessagingStyleMessage( + public static List<Notification.MessagingStyle.Message> getMessagingStyleMessages( Notification notification) { if (notification == null) { return null; @@ -312,7 +320,7 @@ public class PeopleSpaceUtils { Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages); sortedMessages.sort(Collections.reverseOrder( Comparator.comparing(Notification.MessagingStyle.Message::getTimestamp))); - return sortedMessages.get(0); + return sortedMessages; } } return null; diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index ae81ab04ec10..bc196bf68b66 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -58,8 +58,10 @@ import com.android.systemui.R; import com.android.systemui.people.widget.LaunchConversationActivity; import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; +import java.text.NumberFormat; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.regex.Matcher; @@ -82,6 +84,8 @@ class PeopleTileViewHelper { private static final int FIXED_HEIGHT_DIMENS_FOR_SMALL = 6 + 4 + 8; private static final int FIXED_WIDTH_DIMENS_FOR_SMALL = 4 + 4; + private static final int MESSAGES_COUNT_OVERFLOW = 7; + private static final Pattern DOUBLE_EXCLAMATION_PATTERN = Pattern.compile("[!][!]+"); private static final Pattern DOUBLE_QUESTION_PATTERN = Pattern.compile("[?][?]+"); private static final Pattern ANY_DOUBLE_MARK_PATTERN = Pattern.compile("[!?][!?]+"); @@ -97,6 +101,9 @@ class PeopleTileViewHelper { private int mHeight; private int mLayoutSize; + private Locale mLocale; + private NumberFormat mIntegerFormat; + PeopleTileViewHelper(Context context, PeopleSpaceTile tile, int appWidgetId, Bundle options) { mContext = context; @@ -354,12 +361,35 @@ class PeopleTileViewHelper { views.setViewVisibility(R.id.image, View.GONE); views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_message); } + if (mTile.getMessagesCount() > 1 && mLayoutSize == LAYOUT_MEDIUM) { + views.setViewVisibility(R.id.messages_count, View.VISIBLE); + views.setTextViewText(R.id.messages_count, + getMessagesCountText(mTile.getMessagesCount())); + } // TODO: Set subtext as Group Sender name once storing the name in PeopleSpaceTile and // subtract 1 from maxLines when present. views.setViewVisibility(R.id.subtext, View.GONE); return views; } + // Some messaging apps only include up to 7 messages in their notifications. + private String getMessagesCountText(int count) { + if (count >= MESSAGES_COUNT_OVERFLOW) { + return mContext.getResources().getString( + R.string.messages_count_overflow_indicator, MESSAGES_COUNT_OVERFLOW); + } + + // Cache the locale-appropriate NumberFormat. Configuration locale is guaranteed + // non-null, so the first time this is called we will always get the appropriate + // NumberFormat, then never regenerate it unless the locale changes on the fly. + final Locale curLocale = mContext.getResources().getConfiguration().getLocales().get(0); + if (!curLocale.equals(mLocale)) { + mLocale = curLocale; + mIntegerFormat = NumberFormat.getIntegerInstance(curLocale); + } + return mIntegerFormat.format(count); + } + private RemoteViews createStatusRemoteViews(ConversationStatus status) { RemoteViews views = getViewForContentLayout(); CharSequence statusText = status.getDescription(); diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java index 4ad685eae107..776e8a246bf6 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java @@ -328,6 +328,7 @@ public class PeopleSpaceWidgetManager { .setNotificationKey(null) .setNotificationContent(null) .setNotificationDataUri(null) + .setMessagesCount(0) // Reset missed calls category. .setNotificationCategory(null) .build(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java index 1c7a84a36404..1f4dffa09d86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java @@ -65,6 +65,7 @@ import android.util.DisplayMetrics; import androidx.test.filters.SmallTest; import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.util.ArrayUtils; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.people.widget.PeopleTileKey; @@ -119,6 +120,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { .setNotificationKey(NOTIFICATION_KEY) .setNotificationContent(NOTIFICATION_CONTENT) .setNotificationDataUri(URI) + .setMessagesCount(1) .build(); private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext, @@ -318,7 +320,7 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { } @Test - public void testGetLastMessagingStyleMessageNoMessage() { + public void testGetMessagingStyleMessagesNoMessage() { Notification notification = new Notification.Builder(mContext, "test") .setContentTitle("TEST_TITLE") .setContentText("TEST_TEXT") @@ -328,22 +330,23 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase { .setNotification(notification) .build(); - Notification.MessagingStyle.Message lastMessage = - PeopleSpaceUtils.getLastMessagingStyleMessage(sbn.getNotification()); + List<Notification.MessagingStyle.Message> messages = + PeopleSpaceUtils.getMessagingStyleMessages(sbn.getNotification()); - assertThat(lastMessage).isNull(); + assertThat(ArrayUtils.isEmpty(messages)).isTrue(); } @Test - public void testGetLastMessagingStyleMessage() { + public void testGetMessagingStyleMessages() { StatusBarNotification sbn = new SbnBuilder() .setNotification(mNotification1) .build(); - Notification.MessagingStyle.Message lastMessage = - PeopleSpaceUtils.getLastMessagingStyleMessage(sbn.getNotification()); + List<Notification.MessagingStyle.Message> messages = + PeopleSpaceUtils.getMessagingStyleMessages(sbn.getNotification()); - assertThat(lastMessage.getText().toString()).isEqualTo(NOTIFICATION_TEXT_2); + assertThat(messages.size()).isEqualTo(3); + assertThat(messages.get(0).getText().toString()).isEqualTo(NOTIFICATION_TEXT_2); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java index 39bf06050741..c2e0d6b49a76 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java @@ -467,6 +467,9 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { assertEquals(View.VISIBLE, smallResult.findViewById(R.id.person_icon).getVisibility()); + // Has a single message, no count shown. + assertEquals(View.GONE, result.findViewById(R.id.messages_count).getVisibility()); + mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, getSizeInDp(R.dimen.required_width_for_large)); mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH, @@ -492,6 +495,36 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { } @Test + public void testCreateRemoteViewsWithNotificationTemplateTwoMessages() { + PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder() + .setNotificationDataUri(null) + .setStatuses(Arrays.asList(GAME_STATUS, + NEW_STORY_WITH_AVAILABILITY)) + .setMessagesCount(2).build(); + RemoteViews views = new PeopleTileViewHelper(mContext, + tileWithStatusAndNotification, 0, mOptions).getViews(); + View result = views.apply(mContext, null); + + TextView name = (TextView) result.findViewById(R.id.name); + assertEquals(name.getText(), NAME); + TextView subtext = (TextView) result.findViewById(R.id.subtext); + assertEquals(View.GONE, subtext.getVisibility()); + // Has availability. + View availability = result.findViewById(R.id.availability); + assertEquals(View.VISIBLE, availability.getVisibility()); + // Has person icon. + View personIcon = result.findViewById(R.id.person_icon); + assertEquals(View.VISIBLE, personIcon.getVisibility()); + // Has notification content. + TextView statusContent = (TextView) result.findViewById(R.id.text_content); + assertEquals(statusContent.getText(), NOTIFICATION_CONTENT); + + // Has 2 messages, show count. + assertEquals(View.VISIBLE, result.findViewById(R.id.messages_count).getVisibility()); + } + + + @Test public void testGetBackgroundTextFromMessageNoPunctuation() { String backgroundText = mPeopleTileViewHelper.getBackgroundTextFromMessage("test"); |