Add new templates & show Statuses in People Tiles
Backup strings provided in the case of missing status text when icons are provided. Implements three layouts to handle our different states. Change-Id: I1cb81c42e4cdd75b000f52c402a7396897c0f027 Test: PeopleSpaceUtilsTest Bug: 178792356
This commit is contained in:
22
packages/SystemUI/res/drawable/circle_green_10dp.xml
Normal file
22
packages/SystemUI/res/drawable/circle_green_10dp.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2020 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"
|
||||
android:shape="oval">
|
||||
<size android:height="10dp"
|
||||
android:width="10dp" />
|
||||
<solid android:color="#34A853" />
|
||||
</shape>
|
||||
@@ -16,5 +16,5 @@
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<solid android:color="?android:attr/colorControlHighlight" />
|
||||
<corners android:radius="@dimen/people_space_widget_radius" />
|
||||
<corners android:radius="@dimen/people_space_image_radius" />
|
||||
</shape>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="?android:attr/colorBackground" />
|
||||
<corners android:radius="@dimen/people_space_widget_round_radius" />
|
||||
<stroke android:width="2dp" android:color="?android:attr/colorAccent" />
|
||||
</shape>
|
||||
@@ -19,70 +19,78 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:background="@drawable/people_space_round_tile_view_card"
|
||||
android:background="@drawable/people_space_tile_view_card"
|
||||
android:id="@+id/item"
|
||||
android:paddingVertical="6dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="12dp"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="2dp"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:background="@drawable/people_space_new_story_outline"
|
||||
android:id="@+id/person_icon_with_story"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp">
|
||||
<ImageView
|
||||
android:id="@+id/person_icon"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp" />
|
||||
android:id="@+id/person_icon_inside_ring"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"/>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_only"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:background="@drawable/people_space_rounded_border"
|
||||
android:layout_marginStart="-12dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:layout_marginBottom="14dp"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/package_icon"
|
||||
android:layout_width="12dp"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_height="12dp" />
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/package_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="-20dp"
|
||||
android:layout_marginTop="22dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:text="@string/empty_user_name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:textSize="14sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:id="@+id/last_interaction"
|
||||
android:text="@string/empty_status"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:paddingVertical="3dp"
|
||||
android:textSize="12sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end" />
|
||||
android:ellipsize="end"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
<?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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<RelativeLayout
|
||||
android:background="@drawable/people_space_tile_view_card"
|
||||
android:id="@+id/people_tile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<include layout="@layout/punctuation_layout"/>
|
||||
<RelativeLayout
|
||||
android:gravity="start"
|
||||
android:id="@+id/column_one"
|
||||
android:paddingVertical="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/subtext"
|
||||
android:layout_toStartOf="@+id/content_layout"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="top|start"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="12sp"
|
||||
android:maxWidth="60dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/avatar_and_app_icon"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:id="@+id/person_icon_with_story"
|
||||
android:background="@drawable/people_space_new_story_outline"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp">
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_inside_ring"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"/>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_only"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"/>
|
||||
<ImageView
|
||||
android:id="@id/package_icon"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="32dp"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_layout"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:gravity="top|end"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/content"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:gravity="top|end"
|
||||
android:textSize="12sp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"/>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_background"
|
||||
android:background="@drawable/people_space_content_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxHeight="44dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/person_label"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:gravity="start|bottom"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/content_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:paddingVertical="2dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
@@ -14,183 +14,144 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<RelativeLayout
|
||||
android:background="@drawable/people_space_tile_view_card"
|
||||
android:id="@+id/people_tile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start">
|
||||
<TextView
|
||||
android:id="@+id/punctuation1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="350" />
|
||||
<TextView
|
||||
android:id="@+id/punctuation2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="5" />
|
||||
<TextView
|
||||
android:id="@+id/punctuation3"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="355"/>
|
||||
<TextView
|
||||
android:id="@+id/punctuation4"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="-5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="10" />
|
||||
<TextView
|
||||
android:id="@+id/punctuation5"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="15" />
|
||||
<TextView
|
||||
android:id="@+id/punctuation6"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="-5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="345" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/item"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="6dp"
|
||||
android:layout_width="match_parent"
|
||||
<RelativeLayout
|
||||
android:gravity="start"
|
||||
android:id="@+id/column_one"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:gravity="top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/person_icon"
|
||||
android:layout_width="34dp"
|
||||
android:layout_height="34dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:background="@drawable/people_space_rounded_border"
|
||||
android:layout_marginStart="-5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/package_icon"
|
||||
android:layout_width="6dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:layout_marginTop="1dp"
|
||||
android:layout_height="6dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="6dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="10sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_background"
|
||||
android:background="@drawable/people_space_content_background"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/content"
|
||||
android:paddingVertical="3dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="16sp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end" />
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp">
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/people_space_content_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:scaleType="centerCrop"/>
|
||||
<ImageView
|
||||
android:id="@+id/status_defined_icon"
|
||||
android:gravity="start|top"
|
||||
android:layout_marginStart="-52dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/avatar_and_app_icon"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:paddingStart="4dp"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:id="@+id/person_icon_with_story"
|
||||
android:background="@drawable/people_space_new_story_outline"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp">
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_inside_ring"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"/>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/person_icon_only"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"/>
|
||||
<ImageView
|
||||
android:id="@id/package_icon"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="32dp"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/content_layout"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:gravity="top|end"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="12sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/person_label"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:gravity="start|bottom"
|
||||
android:layout_toEndOf="@id/column_one"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/content_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="12sp"
|
||||
android:paddingVertical="2dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:visibility="gone"
|
||||
android:ellipsize="end"/>
|
||||
<ImageView
|
||||
android:id="@+id/availability"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:paddingVertical="2dp"
|
||||
android:background="@drawable/circle_green_10dp"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
100
packages/SystemUI/res/layout/punctuation_layout.xml
Normal file
100
packages/SystemUI/res/layout/punctuation_layout.xml
Normal file
@@ -0,0 +1,100 @@
|
||||
<?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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/punctuation_layout"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start">
|
||||
<TextView
|
||||
android:id="@+id/punctuation1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="350"/>
|
||||
<TextView
|
||||
android:id="@+id/punctuation2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="5"/>
|
||||
<TextView
|
||||
android:id="@+id/punctuation3"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="355"/>
|
||||
<TextView
|
||||
android:id="@+id/punctuation4"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="-5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="10"/>
|
||||
<TextView
|
||||
android:id="@+id/punctuation5"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="15"/>
|
||||
<TextView
|
||||
android:id="@+id/punctuation6"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="-5dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:maxLines="1"
|
||||
android:alpha="0.2"
|
||||
android:rotation="345"/>
|
||||
</LinearLayout>
|
||||
@@ -1348,8 +1348,8 @@
|
||||
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
||||
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
|
||||
|
||||
<dimen name="people_space_widget_radius">24dp</dimen>
|
||||
<dimen name="people_space_widget_round_radius">100dp</dimen>
|
||||
<dimen name="people_space_widget_radius">28dp</dimen>
|
||||
<dimen name="people_space_image_radius">20dp</dimen>
|
||||
<dimen name="people_space_widget_background_padding">6dp</dimen>
|
||||
|
||||
<dimen name="rounded_slider_height">48dp</dimen>
|
||||
|
||||
@@ -2810,8 +2810,26 @@
|
||||
<string name="less_than_timestamp" translatable="false">Less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
|
||||
<!-- Timestamp for notification when over a certain time window [CHAR LIMIT=120] -->
|
||||
<string name="over_timestamp" translatable="false">Over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
|
||||
<!-- Status text for a birthday today [CHAR LIMIT=120] -->
|
||||
<string name="birthday_status" translatable="false">Today is their birthday!</string>
|
||||
<!-- Status text for a birthday today [CHAR LIMIT=30] -->
|
||||
<string name="birthday_status" translatable="false">Birthday</string>
|
||||
<!-- Status text for an upcoming birthday [CHAR LIMIT=30] -->
|
||||
<string name="upcoming_birthday_status" translatable="false">Birthday soon</string>
|
||||
<!-- Status text for an anniversary [CHAR LIMIT=30] -->
|
||||
<string name="anniversary_status" translatable="false">Anniversary</string>
|
||||
<!-- Status text for sharing location [CHAR LIMIT=30] -->
|
||||
<string name="location_status" translatable="false">Sharing location</string>
|
||||
<!-- Status text for a new story posted [CHAR LIMIT=30] -->
|
||||
<string name="new_story_status" translatable="false">New story</string>
|
||||
<!-- Status text for watching a video [CHAR LIMIT=30] -->
|
||||
<string name="video_status" translatable="false">Watching</string>
|
||||
<!-- Status text for listening to audio [CHAR LIMIT=30] -->
|
||||
<string name="audio_status" translatable="false">Listening</string>
|
||||
<!-- Status text for playing a game [CHAR LIMIT=30] -->
|
||||
<string name="game_status" translatable="false">Playing</string>
|
||||
<!-- Empty user name before user has selected a friend [CHAR LIMIT=30] -->
|
||||
<string name="empty_user_name" translatable="false">Your friend</string>
|
||||
<!-- Empty status shown before user has selected a friend [CHAR LIMIT=30] -->
|
||||
<string name="empty_status" translatable="false">Their status</string>
|
||||
|
||||
<!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
|
||||
[CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="140dp"
|
||||
android:minHeight="40dp"
|
||||
android:minHeight="55dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="40dp"
|
||||
android:minResizeHeight="55dp"
|
||||
android:updatePeriodMillis="60000"
|
||||
android:previewImage="@drawable/ic_android"
|
||||
android:previewImage="@drawable/ic_person"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:configure="com.android.systemui.people.PeopleSpaceActivity"
|
||||
android:initialLayout="@layout/people_space_widget">
|
||||
|
||||
@@ -17,12 +17,21 @@
|
||||
package com.android.systemui.people;
|
||||
|
||||
import static android.app.Notification.EXTRA_MESSAGES;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_LOCATION;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_MEDIA;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_UPCOMING_BIRTHDAY;
|
||||
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.people.ConversationChannel;
|
||||
import android.app.people.ConversationStatus;
|
||||
import android.app.people.IPeopleManager;
|
||||
import android.app.people.PeopleSpaceTile;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
@@ -37,6 +46,7 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.icu.text.MeasureFormat;
|
||||
import android.icu.util.Measure;
|
||||
import android.icu.util.MeasureUnit;
|
||||
@@ -71,6 +81,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
@@ -441,20 +452,141 @@ public class PeopleSpaceUtils {
|
||||
/** Creates a {@link RemoteViews} for {@code tile}. */
|
||||
public static RemoteViews createRemoteViews(Context context,
|
||||
PeopleSpaceTile tile, int appWidgetId) {
|
||||
RemoteViews views;
|
||||
RemoteViews viewsForTile = getViewForTile(context, tile);
|
||||
RemoteViews views = setCommonRemoteViewsFields(context, viewsForTile, tile);
|
||||
return setLaunchIntents(context, views, tile, appWidgetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The prioritization for the {@code tile} content is missed calls, followed by notification
|
||||
* content, then birthdays, then the most recent status, and finally last interaction.
|
||||
*/
|
||||
private static RemoteViews getViewForTile(Context context, PeopleSpaceTile tile) {
|
||||
if (tile.getNotificationKey() != null) {
|
||||
views = createNotificationRemoteViews(context, tile);
|
||||
} else if (tile.getBirthdayText() != null) {
|
||||
views = createStatusRemoteViews(context, tile);
|
||||
} else {
|
||||
views = createLastInteractionRemoteViews(context, tile);
|
||||
if (DEBUG) Log.d(TAG, "Create notification view");
|
||||
return createNotificationRemoteViews(context, tile);
|
||||
}
|
||||
|
||||
// TODO: Add sorting when we expose timestamp of statuses.
|
||||
List<ConversationStatus> statusesForEntireView =
|
||||
tile.getStatuses() == null ? Arrays.asList() : tile.getStatuses().stream().filter(
|
||||
c -> isStatusValidForEntireStatusView(c)).collect(Collectors.toList());
|
||||
ConversationStatus birthdayStatus = getBirthdayStatus(tile, statusesForEntireView);
|
||||
if (birthdayStatus != null) {
|
||||
if (DEBUG) Log.d(TAG, "Create birthday view");
|
||||
return createStatusRemoteViews(context, birthdayStatus);
|
||||
}
|
||||
|
||||
if (!statusesForEntireView.isEmpty()) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"Create status view for: " + statusesForEntireView.get(0).getActivity());
|
||||
}
|
||||
return createStatusRemoteViews(context, statusesForEntireView.get(0));
|
||||
}
|
||||
|
||||
return createLastInteractionRemoteViews(context, tile);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ConversationStatus getBirthdayStatus(PeopleSpaceTile tile,
|
||||
List<ConversationStatus> statuses) {
|
||||
Optional<ConversationStatus> birthdayStatus = statuses.stream().filter(
|
||||
c -> c.getActivity() == ACTIVITY_BIRTHDAY).findFirst();
|
||||
if (birthdayStatus.isPresent()) {
|
||||
return birthdayStatus.get();
|
||||
}
|
||||
if (!TextUtils.isEmpty(tile.getBirthdayText())) {
|
||||
return new ConversationStatus.Builder(tile.getId(), ACTIVITY_BIRTHDAY).build();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a {@code status} should have its own entire templated view.
|
||||
*
|
||||
* <p>A status may still be shown on the view (for example, as a new story ring) even if it's
|
||||
* not valid to compose an entire view.
|
||||
*/
|
||||
private static boolean isStatusValidForEntireStatusView(ConversationStatus status) {
|
||||
switch (status.getActivity()) {
|
||||
// Birthday & Anniversary don't require text provided or icon provided.
|
||||
case ACTIVITY_BIRTHDAY:
|
||||
case ACTIVITY_ANNIVERSARY:
|
||||
return true;
|
||||
default:
|
||||
// For future birthday, location, new story, video, music, game, and other, the
|
||||
// app must provide either text or an icon.
|
||||
return !TextUtils.isEmpty(status.getDescription())
|
||||
|| status.getIcon() != null;
|
||||
}
|
||||
}
|
||||
|
||||
private static RemoteViews createStatusRemoteViews(Context context, ConversationStatus status) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_small_avatar_tile);
|
||||
CharSequence statusText = status.getDescription();
|
||||
if (TextUtils.isEmpty(statusText)) {
|
||||
statusText = getStatusTextByType(context, status.getActivity());
|
||||
}
|
||||
views.setTextViewText(R.id.status, statusText);
|
||||
Icon statusIcon = status.getIcon();
|
||||
if (statusIcon != null) {
|
||||
views.setImageViewIcon(R.id.image, statusIcon);
|
||||
views.setBoolean(R.id.content_background, "setClipToOutline", true);
|
||||
} else {
|
||||
views.setViewVisibility(R.id.content_background, View.GONE);
|
||||
}
|
||||
// TODO: Set status pre-defined icons
|
||||
return views;
|
||||
}
|
||||
|
||||
private static String getStatusTextByType(Context context, int activity) {
|
||||
switch (activity) {
|
||||
case ACTIVITY_BIRTHDAY:
|
||||
return context.getString(R.string.birthday_status);
|
||||
case ACTIVITY_UPCOMING_BIRTHDAY:
|
||||
return context.getString(R.string.upcoming_birthday_status);
|
||||
case ACTIVITY_ANNIVERSARY:
|
||||
return context.getString(R.string.anniversary_status);
|
||||
case ACTIVITY_LOCATION:
|
||||
return context.getString(R.string.location_status);
|
||||
case ACTIVITY_NEW_STORY:
|
||||
return context.getString(R.string.new_story_status);
|
||||
case ACTIVITY_MEDIA:
|
||||
return context.getString(R.string.video_status);
|
||||
case ACTIVITY_GAME:
|
||||
return context.getString(R.string.game_status);
|
||||
default:
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
return setCommonRemoteViewsFields(context, views, tile, appWidgetId);
|
||||
}
|
||||
|
||||
private static RemoteViews setCommonRemoteViewsFields(Context context, RemoteViews views,
|
||||
PeopleSpaceTile tile, int appWidgetId) {
|
||||
PeopleSpaceTile tile) {
|
||||
try {
|
||||
boolean isAvailable =
|
||||
tile.getStatuses() != null && tile.getStatuses().stream().anyMatch(
|
||||
c -> c.getAvailability() == AVAILABILITY_AVAILABLE);
|
||||
if (isAvailable) {
|
||||
views.setViewVisibility(R.id.availability, View.VISIBLE);
|
||||
} else {
|
||||
views.setViewVisibility(R.id.availability, View.GONE);
|
||||
}
|
||||
boolean hasNewStory =
|
||||
tile.getStatuses() != null && tile.getStatuses().stream().anyMatch(
|
||||
c -> c.getActivity() == ACTIVITY_NEW_STORY);
|
||||
if (hasNewStory) {
|
||||
views.setViewVisibility(R.id.person_icon_with_story, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.person_icon_only, View.GONE);
|
||||
views.setImageViewIcon(R.id.person_icon_inside_ring, tile.getUserIcon());
|
||||
} else {
|
||||
views.setViewVisibility(R.id.person_icon_with_story, View.GONE);
|
||||
views.setViewVisibility(R.id.person_icon_only, View.VISIBLE);
|
||||
views.setImageViewIcon(R.id.person_icon_only, tile.getUserIcon());
|
||||
}
|
||||
|
||||
views.setTextViewText(R.id.name, tile.getUserName().toString());
|
||||
views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
|
||||
views.setBoolean(R.id.content_background, "setClipToOutline", true);
|
||||
@@ -466,7 +598,16 @@ public class PeopleSpaceUtils {
|
||||
tile.getPackageName())
|
||||
)
|
||||
);
|
||||
return views;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to set common fields: " + e);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
private static RemoteViews setLaunchIntents(Context context, RemoteViews views,
|
||||
PeopleSpaceTile tile, int appWidgetId) {
|
||||
try {
|
||||
Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
|
||||
activityIntent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
@@ -484,48 +625,42 @@ public class PeopleSpaceUtils {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
|
||||
return views;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to set common fields: " + e);
|
||||
Log.e(TAG, "Failed to add launch intents: " + e);
|
||||
}
|
||||
return null;
|
||||
return views;
|
||||
}
|
||||
|
||||
private static RemoteViews createNotificationRemoteViews(Context context,
|
||||
PeopleSpaceTile tile) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_small_avatar_tile);
|
||||
context.getPackageName(), R.layout.people_space_notification_content_tile);
|
||||
Uri image = tile.getNotificationDataUri();
|
||||
if (image != null) {
|
||||
//TODO: Use NotificationInlineImageCache
|
||||
// TODO: Use NotificationInlineImageCache
|
||||
views.setImageViewUri(R.id.image, image);
|
||||
views.setViewVisibility(R.id.image, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.content_background, View.VISIBLE);
|
||||
views.setBoolean(R.id.content_background, "setClipToOutline", true);
|
||||
views.setViewVisibility(R.id.content, View.GONE);
|
||||
} else {
|
||||
CharSequence content = tile.getNotificationContent();
|
||||
views = setPunctuationRemoteViewsFields(views, content);
|
||||
views.setTextViewText(R.id.content, content);
|
||||
views.setViewVisibility(R.id.content, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.image, View.GONE);
|
||||
views.setViewVisibility(R.id.content_background, View.GONE);
|
||||
}
|
||||
views.setTextViewText(R.id.time, PeopleSpaceUtils.getLastInteractionString(
|
||||
// TODO: Set subtext as Group Sender name once storing the name in PeopleSpaceTile.
|
||||
views.setTextViewText(R.id.subtext, PeopleSpaceUtils.getLastInteractionString(
|
||||
context, tile.getLastInteractionTimestamp(), false));
|
||||
return views;
|
||||
}
|
||||
|
||||
private static RemoteViews createStatusRemoteViews(Context context,
|
||||
PeopleSpaceTile tile) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_large_avatar_tile);
|
||||
views.setTextViewText(R.id.status, tile.getBirthdayText());
|
||||
return views;
|
||||
}
|
||||
|
||||
private static RemoteViews createLastInteractionRemoteViews(Context context,
|
||||
PeopleSpaceTile tile) {
|
||||
RemoteViews views = new RemoteViews(
|
||||
context.getPackageName(), R.layout.people_space_large_avatar_tile);
|
||||
String status = PeopleSpaceUtils.getLastInteractionString(
|
||||
context, tile.getLastInteractionTimestamp(), true);
|
||||
views.setTextViewText(R.id.status, status);
|
||||
views.setTextViewText(R.id.last_interaction, status);
|
||||
return views;
|
||||
}
|
||||
|
||||
@@ -682,20 +817,35 @@ public class PeopleSpaceUtils {
|
||||
Duration durationSinceLastInteraction = Duration.ofMillis(now - lastInteraction);
|
||||
MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
|
||||
MeasureFormat.FormatWidth.WIDE);
|
||||
MeasureFormat shortFormatter = MeasureFormat.getInstance(Locale.getDefault(),
|
||||
MeasureFormat.FormatWidth.SHORT);
|
||||
if (durationSinceLastInteraction.toHours() < MIN_HOUR) {
|
||||
return context.getString(includeLastChatted ? R.string.last_interaction_status_less_than
|
||||
: R.string.less_than_timestamp,
|
||||
formatter.formatMeasures(new Measure(MIN_HOUR, MeasureUnit.HOUR)));
|
||||
if (includeLastChatted) {
|
||||
return context.getString(R.string.last_interaction_status_less_than,
|
||||
formatter.formatMeasures(new Measure(MIN_HOUR, MeasureUnit.HOUR)));
|
||||
}
|
||||
return context.getString(R.string.timestamp, shortFormatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toMinutes(), MeasureUnit.MINUTE)));
|
||||
} else if (durationSinceLastInteraction.toDays() < ONE_DAY) {
|
||||
return context.getString(
|
||||
includeLastChatted ? R.string.last_interaction_status : R.string.timestamp,
|
||||
formatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toHours(), MeasureUnit.HOUR)));
|
||||
if (includeLastChatted) {
|
||||
return context.getString(R.string.last_interaction_status,
|
||||
formatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toHours(),
|
||||
MeasureUnit.HOUR)));
|
||||
}
|
||||
return context.getString(R.string.timestamp, shortFormatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toHours(),
|
||||
MeasureUnit.HOUR)));
|
||||
} else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK) {
|
||||
return context.getString(
|
||||
includeLastChatted ? R.string.last_interaction_status : R.string.timestamp,
|
||||
formatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toDays(), MeasureUnit.DAY)));
|
||||
if (includeLastChatted) {
|
||||
return context.getString(R.string.last_interaction_status,
|
||||
formatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toDays(),
|
||||
MeasureUnit.DAY)));
|
||||
}
|
||||
return context.getString(R.string.timestamp, shortFormatter.formatMeasures(
|
||||
new Measure(durationSinceLastInteraction.toHours(),
|
||||
MeasureUnit.DAY)));
|
||||
} else {
|
||||
return context.getString(durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK
|
||||
? (includeLastChatted ? R.string.last_interaction_status :
|
||||
|
||||
@@ -16,11 +16,18 @@
|
||||
|
||||
package com.android.systemui.people;
|
||||
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
|
||||
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
|
||||
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
|
||||
|
||||
import static com.android.systemui.people.PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE;
|
||||
import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -39,6 +46,7 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Person;
|
||||
import android.app.people.ConversationChannel;
|
||||
import android.app.people.ConversationStatus;
|
||||
import android.app.people.IPeopleManager;
|
||||
import android.app.people.PeopleSpaceTile;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
@@ -46,13 +54,13 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.Settings;
|
||||
@@ -60,6 +68,9 @@ import android.service.notification.ConversationChannelWrapper;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.appwidget.IAppWidgetService;
|
||||
import com.android.systemui.R;
|
||||
@@ -101,27 +112,45 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
private static final int TEST_COLUMN_INDEX = 1;
|
||||
private static final Uri URI = Uri.parse("fake_uri");
|
||||
private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
|
||||
private static final String GAME_DESCRIPTION = "Playing a game!";
|
||||
private static final String NAME = "username";
|
||||
private static final Person PERSON = new Person.Builder()
|
||||
.setName("name")
|
||||
.setKey("abc")
|
||||
.setUri(URI.toString())
|
||||
.setBot(false)
|
||||
.build();
|
||||
private static final PeopleSpaceTile PERSON_TILE_WITHOUT_NOTIFICATION =
|
||||
new PeopleSpaceTile
|
||||
.Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
|
||||
.setLastInteractionTimestamp(0L)
|
||||
.build();
|
||||
private static final PeopleSpaceTile PERSON_TILE =
|
||||
new PeopleSpaceTile
|
||||
.Builder(SHORTCUT_ID_1, "username", ICON, new Intent())
|
||||
.Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
|
||||
.setLastInteractionTimestamp(123L)
|
||||
.setNotificationKey(NOTIFICATION_KEY)
|
||||
.setNotificationContent(NOTIFICATION_CONTENT)
|
||||
.setNotificationDataUri(URI)
|
||||
.build();
|
||||
private static final ConversationStatus GAME_STATUS =
|
||||
new ConversationStatus
|
||||
.Builder(PERSON_TILE.getId(), ACTIVITY_GAME)
|
||||
.setDescription(GAME_DESCRIPTION)
|
||||
.build();
|
||||
private static final ConversationStatus NEW_STORY_WITH_AVAILABILITY =
|
||||
new ConversationStatus
|
||||
.Builder(PERSON_TILE.getId(), ACTIVITY_NEW_STORY)
|
||||
.setAvailability(AVAILABILITY_AVAILABLE)
|
||||
.build();
|
||||
|
||||
private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext,
|
||||
SHORTCUT_ID_1).setLongLabel(
|
||||
"name").setPerson(PERSON)
|
||||
NAME).setPerson(PERSON)
|
||||
.build();
|
||||
private final ShortcutInfo mShortcutInfoWithoutPerson = new ShortcutInfo.Builder(mContext,
|
||||
SHORTCUT_ID_1).setLongLabel(
|
||||
"name")
|
||||
NAME)
|
||||
.build();
|
||||
private final Notification mNotification1 = new Notification.Builder(mContext, "test")
|
||||
.setContentTitle("TEST_TITLE")
|
||||
@@ -189,10 +218,12 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private Context mMockContext;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private NotificationEntryManager mNotificationEntryManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws RemoteException {
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
|
||||
@@ -212,6 +243,12 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
isNull())).thenReturn(mMockCursor);
|
||||
when(mMockContext.getString(R.string.birthday_status)).thenReturn(
|
||||
mContext.getString(R.string.birthday_status));
|
||||
when(mMockContext.getString(R.string.basic_status)).thenReturn(
|
||||
mContext.getString(R.string.basic_status));
|
||||
when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mMockContext.getString(R.string.over_timestamp)).thenReturn(
|
||||
mContext.getString(R.string.over_timestamp));
|
||||
when(mPackageManager.getApplicationIcon(anyString())).thenReturn(null);
|
||||
when(mNotificationEntryManager.getVisibleNotifications())
|
||||
.thenReturn(List.of(mNotificationEntry1, mNotificationEntry2, mNotificationEntry3));
|
||||
}
|
||||
@@ -621,6 +658,137 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithLastInteractionTime() {
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mMockContext,
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION, 0);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
assertEquals(name.getText(), NAME);
|
||||
// Has last interaction.
|
||||
TextView lastInteraction = (TextView) result.findViewById(R.id.last_interaction);
|
||||
assertEquals(lastInteraction.getText(), mContext.getString(R.string.basic_status));
|
||||
// No availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.GONE, availability.getVisibility());
|
||||
// No new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.VISIBLE, personIcon.getVisibility());
|
||||
assertEquals(View.GONE, personIconWithStory.getVisibility());
|
||||
// No status.
|
||||
assertThat((View) result.findViewById(R.id.status)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithGameTypeOnlyIsIgnored() {
|
||||
PeopleSpaceTile tileWithAvailabilityAndNewStory =
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
|
||||
Arrays.asList(NEW_STORY_WITH_AVAILABILITY,
|
||||
new ConversationStatus.Builder(
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
|
||||
ACTIVITY_GAME).build())).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mMockContext,
|
||||
tileWithAvailabilityAndNewStory, 0);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
assertEquals(name.getText(), NAME);
|
||||
// Has last interaction over status.
|
||||
TextView lastInteraction = (TextView) result.findViewById(R.id.last_interaction);
|
||||
assertEquals(lastInteraction.getText(), mContext.getString(R.string.basic_status));
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// No status.
|
||||
assertThat((View) result.findViewById(R.id.status)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithBirthdayTypeOnlyIsNotIgnored() {
|
||||
PeopleSpaceTile tileWithStatusTemplate =
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
|
||||
Arrays.asList(
|
||||
NEW_STORY_WITH_AVAILABILITY, new ConversationStatus.Builder(
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
|
||||
ACTIVITY_BIRTHDAY).build())).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusTemplate, 0);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
assertEquals(name.getText(), NAME);
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has status text from backup text.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.status);
|
||||
assertEquals(statusContent.getText(), mContext.getString(R.string.birthday_status));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithStatusTemplate() {
|
||||
PeopleSpaceTile tileWithStatusTemplate =
|
||||
PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
|
||||
Arrays.asList(GAME_STATUS,
|
||||
NEW_STORY_WITH_AVAILABILITY)).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusTemplate, 0);
|
||||
View result = views.apply(mContext, null);
|
||||
|
||||
TextView name = (TextView) result.findViewById(R.id.name);
|
||||
assertEquals(name.getText(), NAME);
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has status.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.status);
|
||||
assertEquals(statusContent.getText(), GAME_DESCRIPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRemoteViewsWithNotificationTemplate() {
|
||||
PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder()
|
||||
.setNotificationDataUri(null)
|
||||
.setStatuses(Arrays.asList(GAME_STATUS,
|
||||
NEW_STORY_WITH_AVAILABILITY)).build();
|
||||
RemoteViews views = PeopleSpaceUtils.createRemoteViews(mContext,
|
||||
tileWithStatusAndNotification, 0);
|
||||
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);
|
||||
assertTrue(subtext.getText().toString().contains("weeks ago"));
|
||||
// Has availability.
|
||||
View availability = result.findViewById(R.id.availability);
|
||||
assertEquals(View.VISIBLE, availability.getVisibility());
|
||||
// Has new story.
|
||||
View personIcon = result.findViewById(R.id.person_icon_only);
|
||||
View personIconWithStory = result.findViewById(R.id.person_icon_with_story);
|
||||
assertEquals(View.GONE, personIcon.getVisibility());
|
||||
assertEquals(View.VISIBLE, personIconWithStory.getVisibility());
|
||||
// Has notification content.
|
||||
TextView statusContent = (TextView) result.findViewById(R.id.content);
|
||||
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
|
||||
}
|
||||
|
||||
private ConversationChannelWrapper getConversationChannelWrapper(String shortcutId,
|
||||
boolean importantConversation, long lastInteractionTimestamp) throws Exception {
|
||||
ConversationChannelWrapper convo = new ConversationChannelWrapper();
|
||||
|
||||
Reference in New Issue
Block a user