Update conversation style.

1) No more blue/green for outgoing messages. Just lock or no lock.

2) Use 9-patches instead of shapes for better bubble performance.

3) Use tinting rather than different colored assets.

4) Change outgoing status indicators so that they don't change
   width of the bubble as they update.

5) Switch to using ..., check, double-check for pending, sent,
   delivered rather than using bubble tone to indicate pending.

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2015-06-29 08:49:32 -07:00
parent 296796eb54
commit db9656c70c
49 changed files with 475 additions and 908 deletions

View File

@ -5,7 +5,7 @@
android:versionCode="131"
android:versionName="2.20.0">
<uses-sdk tools:overrideLibrary="com.amulyakhare.textdrawable,com.astuetz.pagerslidingtabstrip"/>
<uses-sdk tools:overrideLibrary="com.amulyakhare.textdrawable,com.astuetz.pagerslidingtabstrip,pl.tajchert.waitingdots"/>
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
android:label="Access to TextSecure Secrets"

View File

@ -49,6 +49,7 @@ dependencies {
exclude module: 'support-annotations'
}
compile 'pl.tajchert:waitingdots:0.1.0'
compile 'com.soundcloud.android:android-crop:0.9.10@aar'
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.android.support:recyclerview-v7:21.0.3'

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

View File

@ -3,14 +3,14 @@
<item>
<shape android:shape="rectangle">
<solid android:color="#09000000" />
<solid android:color="#0d000000" />
<corners android:radius="@dimen/message_bubble_corner_radius" />
</shape>
</item>
<item android:bottom="@dimen/message_bubble_shadow_distance">
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/conversation_item_received_background_light" />
<solid android:color="#fff3f3f3" />
<corners android:bottomLeftRadius="@dimen/message_bubble_corner_radius" android:bottomRightRadius="@dimen/message_bubble_corner_radius" />
</shape>
</item>

View File

@ -10,7 +10,7 @@
<item android:bottom="@dimen/message_bubble_shadow_distance">
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/conversation_item_received_background_dark" />
<solid android:color="#cc333333" />
<corners android:bottomLeftRadius="@dimen/message_bubble_corner_radius" android:bottomRightRadius="@dimen/message_bubble_corner_radius" />
</shape>
</item>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="110%"
android:pivotY="120%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_received_background_dark" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="110%"
android:pivotY="120%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_received_background_light" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_push_pending_background_dark" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_push_pending_background_light" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_pending_background_dark" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_pending_background_light" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_push_background_dark" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_push_background_light" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_background_dark" />
</shape>
</rotate>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="0%"
android:pivotY="-30%">
<shape android:shape="rectangle">
<solid android:color="@color/conversation_item_sent_background_light" />
</shape>
</rotate>

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?conversation_background"
android:orientation="vertical">
<RelativeLayout

View File

@ -1,121 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View android:id="@+id/triangle_tick"
android:layout_width="12dp"
android:layout_height="15dp"
android:layout_marginTop="12dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<LinearLayout android:id="@+id/thumbnail_container"
android:layout_toRightOf="@id/triangle_tick"
android:layout_toEndOf="@id/triangle_tick"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/media_bubble_height"
android:layout_marginRight="@dimen/message_bubble_end_padding"
android:visibility="gone"
android:layout_gravity="center"
android:scaleType="centerInside"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
app:riv_border_width="@dimen/media_bubble_border_width"
tools:src="@drawable/ic_video_light" />
</LinearLayout>
<LinearLayout android:id="@+id/body_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/triangle_tick"
android:layout_toEndOf="@id/triangle_tick"
android:layout_below="@id/thumbnail_container"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/conversation_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?conversation_received_text_primary_color"
android:textSize="16sp"
android:autoLink="all"
android:linksClickable="true" />
<LinearLayout android:id="@+id/mms_download_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/mms_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/conversation_item_received__download"
android:visibility="gone" />
<TextView android:id="@+id/mms_label_downloading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center"
android:text="@string/conversation_item_received__downloading"
android:visibility="gone" />
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dip"
android:paddingLeft="8dp"
android:paddingRight="5dp"
android:paddingBottom="5dp"
android:orientation="horizontal"
android:gravity="left">
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="3dip"
android:src="?conversation_delivery_delivered"
android:contentDescription="@string/conversation_item_sent__delivered_description"
android:visibility="gone" />
<ImageView android:id="@+id/sms_secure_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="4dp"
android:paddingTop="2dp"
android:src="?menu_lock_icon_small_received"
android:contentDescription="@string/conversation_item__secure_message_description"
android:visibility="gone" />
<TextView android:id="@+id/conversation_item_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:paddingTop="1dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?conversation_received_text_secondary_color"
android:textSize="@dimen/conversation_item_date_text_size"
android:fontFamily="sans-serif-light"
android:autoLink="none"
android:linksClickable="false" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View android:id="@+id/triangle_tick"
android:layout_width="12dp"
android:layout_height="15dp"
android:layout_alignParentRight="true"
android:layout_marginTop="12dp" />
<LinearLayout android:id="@+id/thumbnail_container"
android:layout_width="wrap_content"
android:layout_toLeftOf="@id/triangle_tick"
android:layout_gravity="center"
android:layout_height="wrap_content">
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/media_bubble_height"
android:layout_marginLeft="@dimen/message_bubble_end_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
app:riv_border_width="@dimen/media_bubble_border_width"
tools:src="@drawable/ic_video_light"
tools:visibility="visible" />
</LinearLayout>
<LinearLayout android:id="@+id/body_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/thumbnail_container"
android:layout_alignParentRight="true"
android:paddingRight="10dip"
android:paddingLeft="10dip"
android:layout_marginLeft="50dp"
android:layout_marginRight="12dp"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/conversation_item_body"
android:autoLink="all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:linksClickable="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?conversation_sent_text_primary_color"
android:textColorLink="?conversation_sent_text_primary_color"
android:textSize="16sp"
tools:text="Mango pickle lorem ipsum" />
<LinearLayout android:id="@+id/mms_download_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/mms_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/conversation_item_sent__download"
android:visibility="gone" />
<TextView android:id="@+id/mms_label_downloading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center"
android:text="@string/conversation_item_sent__downloading"
android:visibility="gone" />
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="0dip"
android:layout_gravity="right">
<TextView android:id="@+id/group_message_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:linksClickable="false"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_gravity="right"
android:textColor="?conversation_sent_text_secondary_color"
android:visibility="gone"
android:layout_marginRight="8dip"
android:paddingTop="1dip" />
<TextView android:id="@+id/conversation_item_date"
android:autoLink="none"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="15sp"
android:linksClickable="false"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_gravity="right"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_sent_text_secondary_color"
android:textSize="@dimen/conversation_item_date_text_size"
android:paddingTop="1dip"
android:paddingBottom="5dp"
tools:text="30 mins" />
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="?conversation_delivery_delivered"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
<ImageView android:id="@+id/sms_secure_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="?menu_lock_icon_small"
android:visibility="gone"
android:layout_gravity="center_vertical|end"
android:paddingLeft="2dp"
android:paddingBottom="3dp"
android:contentDescription="@string/conversation_item__secure_message_description" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -25,7 +25,7 @@
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_gravity="right"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_sent_text_secondary_color"
android:textColor="?conversation_item_sent_text_secondary_color"
android:text="date"
android:layout_marginBottom="8dp"
android:visibility="gone"/>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/pending_indicator"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_item_sent_text_secondary_color"
android:textSize="@dimen/conversation_item_date_text_size"
android:paddingTop="1dip"
android:paddingLeft="2dip"
android:paddingBottom="5dp"
android:text="..."/>
</merge>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dots="http://schemas.android.com/apk/res-auto">
<pl.tajchert.sample.DotsTextView
android:id="@+id/pending_indicator"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_item_sent_text_secondary_color"
android:textSize="@dimen/conversation_item_date_text_size"
android:paddingTop="1dip"
android:paddingLeft="2dip"
android:paddingBottom="5dp"
dots:period="150"
dots:autoplay="true"/>
</merge>

View File

@ -7,6 +7,7 @@
android:background="?conversation_item_background"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:dots="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView android:id="@+id/group_message_status"
@ -31,16 +32,118 @@
android:foreground="@drawable/contact_photo_background"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:cropToPadding="true"
android:contentDescription="@string/conversation_item_received__contact_photo_description" />
<org.thoughtcrime.securesms.components.IncomingBubbleContainer
android:id="@+id/bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="29dp" />
<LinearLayout android:id="@+id/body_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/contact_photo"
android:layout_toEndOf="@id/contact_photo"
android:background="@drawable/received_bubble"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/media_bubble_height"
android:layout_marginLeft="4dip"
android:layout_marginTop="4dip"
android:layout_marginRight="4dip"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
app:riv_border_width="0dp"
tools:src="@drawable/ic_video_light"
tools:visibility="visible" />
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/conversation_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?conversation_received_text_primary_color"
android:textSize="16sp"
android:autoLink="all"
android:linksClickable="true" />
<LinearLayout android:id="@+id/mms_download_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/mms_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/conversation_item_received__download"
android:visibility="gone" />
<TextView android:id="@+id/mms_label_downloading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center"
android:text="@string/conversation_item_received__downloading"
android:visibility="gone" />
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dip"
android:paddingLeft="8dp"
android:paddingRight="5dp"
android:paddingBottom="5dp"
android:orientation="horizontal"
android:gravity="left">
<ImageView android:id="@+id/sent_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<ImageView android:id="@+id/secure_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingRight="4dp"
android:paddingTop="2dp"
android:src="?menu_lock_icon_small_received"
android:contentDescription="@string/conversation_item__secure_message_description"
android:visibility="gone" />
<FrameLayout android:id="@+id/pending_indicator_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="@+id/conversation_item_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:paddingTop="1dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?conversation_received_text_secondary_color"
android:textSize="@dimen/conversation_item_date_text_size"
android:fontFamily="sans-serif-light"
android:autoLink="none"
android:linksClickable="false" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
@ -55,7 +158,35 @@
android:src="@drawable/ic_action_warning_red"
android:contentDescription="@string/conversation_item_sent__send_failed_indicator_description"
android:visibility="gone" />
<ImageView
android:id="@+id/pending_approval_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_info_outline_grey600_24dp"
android:visibility="gone"
android:layout_gravity="center_vertical"
android:contentDescription="@string/conversation_item_sent__pending_approval_description"
tools:visibility="gone" />
</LinearLayout>
<TextView android:id="@+id/indicator_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/body_bubble"
android:layout_alignParentRight="true"
android:paddingRight="5dip"
android:paddingLeft="5dip"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="22dp"
android:layout_marginTop="-2dp"
android:textSize="12sp"
android:textColor="?conversation_item_sent_text_indicator_tab_color"
android:background="?conversation_item_sent_indicator_text_background"
android:visibility="gone" />
</RelativeLayout>
</org.thoughtcrime.securesms.ConversationItem>

View File

@ -46,25 +46,151 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.OutgoingBubbleContainer
android:id="@+id/bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/body_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingRight="15dip"
android:paddingLeft="5dip"
android:layout_marginLeft="50dp"
android:layout_marginRight="12dp"
android:background="@drawable/sent_bubble"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/media_bubble_height"
android:layout_marginTop="4dip"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
app:riv_border_width="0dp"
tools:src="@drawable/ic_video_light"
tools:visibility="visible" />
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/conversation_item_body"
android:autoLink="all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:linksClickable="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?conversation_item_sent_text_primary_color"
android:textColorLink="?conversation_item_sent_text_primary_color"
android:textSize="16sp"
tools:text="Mango pickle lorem ipsum" />
<LinearLayout android:id="@+id/mms_download_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/mms_download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/conversation_item_sent__download"
android:visibility="gone" />
<TextView android:id="@+id/mms_label_downloading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center"
android:text="@string/conversation_item_sent__downloading"
android:visibility="gone" />
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="0dip"
android:layout_gravity="right">
<TextView android:id="@+id/group_message_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:linksClickable="false"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_gravity="right"
android:textColor="?conversation_item_sent_text_secondary_color"
android:visibility="gone"
android:layout_marginRight="8dip"
android:paddingTop="1dip" />
<TextView android:id="@+id/conversation_item_date"
android:autoLink="none"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="15sp"
android:linksClickable="false"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_gravity="right"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_item_sent_text_secondary_color"
android:textSize="@dimen/conversation_item_date_text_size"
android:paddingTop="1dip"
android:paddingBottom="5dp"
tools:text="30 mins" />
<FrameLayout android:id="@+id/pending_indicator_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView android:id="@+id/sent_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_done_grey600_18dp"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_done_all_grey600_18dp"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
<ImageView android:id="@+id/secure_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="?menu_lock_icon_small"
android:visibility="gone"
android:layout_gravity="center_vertical|end"
android:paddingLeft="2dp"
android:paddingBottom="3dp"
android:contentDescription="@string/conversation_item__secure_message_description" />
</LinearLayout>
</LinearLayout>
<TextView android:id="@+id/indicator_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/bubble"
android:layout_below="@id/body_bubble"
android:layout_alignParentRight="true"
android:paddingRight="5dip"
android:paddingLeft="5dip"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="15dp"
android:layout_marginTop="-2dp"
android:layout_marginRight="22dp"
android:layout_marginTop="-1dp"
android:textSize="12sp"
android:textColor="?conversation_sent_text_indicator_tab_color"
android:textColor="?conversation_item_sent_text_indicator_tab_color"
android:background="?conversation_item_sent_indicator_text_background"
android:visibility="gone" />

View File

@ -13,9 +13,6 @@
<attr name="conversation_sent_card_background" format="reference|color"/>
<attr name="conversation_group_member_name" format="reference|color"/>
<attr name="conversation_sent_text_primary_color" format="reference|color"/>
<attr name="conversation_sent_text_secondary_color" format="reference|color"/>
<attr name="conversation_sent_text_indicator_tab_color" format="reference|color"/>
<attr name="conversation_received_card_background" format="reference|color"/>
<attr name="conversation_received_text_primary_color" format="reference|color"/>
<attr name="conversation_received_text_secondary_color" format="reference|color"/>
@ -26,9 +23,9 @@
<attr name="centered_app_title_color" format="reference|color" />
<attr name="ic_arrow_forward" format="reference" />
<attr name="conversation_background" format="reference|color"/>
<attr name="conversation_editor_background" format="reference|color"/>
<attr name="conversation_editor_text_color" format="reference|color"/>
<attr name="conversation_delivery_delivered" format="reference"/>
<attr name="conversation_transport_sms_indicator" format="reference"/>
<attr name="conversation_transport_push_indicator" format="reference"/>
<attr name="conversation_transport_popup_background" format="reference"/>
@ -57,20 +54,11 @@
<attr name="emoji_category_emoticons" format="reference"/>
<attr name="conversation_item_background" format="reference"/>
<attr name="conversation_item_received_background" format="reference" />
<attr name="conversation_item_sent_background" format="color" />
<attr name="conversation_item_sent_pending_background" format="color" />
<attr name="conversation_item_sent_push_background" format="color" />
<attr name="conversation_item_bubble_background" format="reference|color"/>
<attr name="conversation_item_sent_text_primary_color" format="reference|color"/>
<attr name="conversation_item_sent_text_secondary_color" format="reference|color"/>
<attr name="conversation_item_sent_text_indicator_tab_color" format="reference|color"/>
<attr name="conversation_item_sent_indicator_text_background" format="reference" />
<attr name="conversation_item_sent_push_pending_background" format="reference" />
<attr name="conversation_item_shadow" format="color" />
<attr name="conversation_item_mms_pending_mask" format="color" />
<attr name="triangle_tick_incoming" format="reference" />
<attr name="triangle_tick_outgoing_sent_sms" format="reference" />
<attr name="triangle_tick_outgoing_sent_push" format="reference" />
<attr name="triangle_tick_outgoing_pending_sms" format="reference" />
<attr name="triangle_tick_outgoing_pending_push" format="reference" />
<attr name="dialog_info_icon" format="reference" />
<attr name="dialog_alert_icon" format="reference" />

View File

@ -35,20 +35,7 @@
<color name="touch_highlight">#400099cc</color>
<color name="light_button">#33ffffff</color>
<color name="light_button_highlight">#66ffffff</color>
<color name="conversation_item_sent_background_dark">#ff284e0a</color>
<color name="conversation_item_sent_background_light">#ff64a926</color>
<color name="conversation_item_sent_shadow_light">#ffd5d5d5</color>
<color name="conversation_item_sent_shadow_dark">#ff222222</color>
<color name="conversation_item_sent_pending_background_light">#5564A926</color>
<color name="conversation_item_sent_pending_background_dark">#90284e0a</color>
<color name="conversation_item_sent_push_background_light">#ff2090ea</color>
<color name="conversation_item_sent_push_background_dark">#ff183b7a</color>
<color name="conversation_item_sent_push_pending_background_light">#ff5cace6</color>
<color name="conversation_item_sent_push_pending_background_dark">#ff122d5e</color>
<color name="conversation_item_received_background_light">#fff3f3f3</color>
<color name="conversation_item_received_background_dark">#ff333333</color>
<color name="conversation_item_received_shadow_light">#ffefefef</color>
<color name="conversation_item_received_shadow_dark">#ff222222</color>
<color name="import_export_item_background_light">#ffeeeeee</color>
<color name="import_export_item_background_dark">#ff333333</color>
<color name="import_export_item_background_shadow_light">#ffd5d5d5</color>

View File

@ -77,9 +77,6 @@
<item name="lower_right_divet">@drawable/divet_lower_right_dark</item>
<item name="conversation_group_member_name">#99000000</item>
<item name="conversation_sent_text_primary_color">#ffffffff</item>
<item name="conversation_sent_text_secondary_color">#bbffffff</item>
<item name="conversation_sent_text_indicator_tab_color">#99000000</item>
<item name="conversation_received_text_primary_color">#ff333333</item>
<item name="conversation_received_text_secondary_color">#99333333</item>
@ -88,9 +85,9 @@
<item name="contact_selection_label_text">#66000000</item>
<item name="conversation_selection_header_text">#44000000</item>
<item name="conversation_background">#eeeeee</item>
<item name="conversation_editor_background">#22000000</item>
<item name="conversation_editor_text_color">#ff111111</item>
<item name="conversation_delivery_delivered">@drawable/ic_delivery_delivered_dark</item>
<item name="conversation_transport_sms_indicator">@drawable/ic_send_sms_insecure</item>
<item name="conversation_transport_push_indicator">@drawable/ic_send_push</item>
<item name="conversation_transport_popup_background">@color/white</item>
@ -118,21 +115,12 @@
<item name="emoji_category_symbol">@drawable/emoji_category_symbol_light</item>
<item name="emoji_category_emoticons">@drawable/emoji_category_emoticons_light</item>
<item name="conversation_item_sent_text_primary_color">#99000000</item>
<item name="conversation_item_bubble_background">@color/white</item>
<item name="conversation_item_sent_text_secondary_color">#bb000000</item>
<item name="conversation_item_sent_text_indicator_tab_color">#99000000</item>
<item name="conversation_item_background">@drawable/conversation_item_background</item>
<item name="conversation_item_received_background">@color/conversation_item_received_background_light</item>
<item name="conversation_item_sent_background">@color/conversation_item_sent_background_light</item>
<item name="conversation_item_sent_push_background">@color/conversation_item_sent_push_background_light</item>
<item name="conversation_item_sent_pending_background">@color/conversation_item_sent_pending_background_light</item>
<item name="conversation_item_sent_push_pending_background">@color/conversation_item_sent_push_pending_background_light</item>
<item name="conversation_item_sent_indicator_text_background">@drawable/conversation_item_sent_indicator_text_shape</item>
<item name="conversation_item_shadow">@color/conversation_item_received_shadow_light</item>
<item name="conversation_item_mms_pending_mask">#99ffffff</item>
<item name="triangle_tick_incoming">@drawable/triangle_tick_incoming_light</item>
<item name="triangle_tick_outgoing_sent_sms">@drawable/triangle_tick_outgoing_sent_sms_light</item>
<item name="triangle_tick_outgoing_sent_push">@drawable/triangle_tick_outgoing_sent_push_light</item>
<item name="triangle_tick_outgoing_pending_sms">@drawable/triangle_tick_outgoing_pending_sms_light</item>
<item name="triangle_tick_outgoing_pending_push">@drawable/triangle_tick_outgoing_pending_push_light</item>
<item name="dialog_info_icon">@drawable/ic_info_outline_light</item>
<item name="dialog_alert_icon">@drawable/ic_warning_light</item>
@ -151,7 +139,7 @@
<item name="menu_popup_expand">@drawable/ic_launch_white_24dp</item>
<item name="menu_unlock_icon">@drawable/ic_unlocked_white_24dp</item>
<item name="menu_lock_icon">@drawable/ic_lock_white_24dp</item>
<item name="menu_lock_icon_small">@drawable/ic_lock_white_18dp</item>
<item name="menu_lock_icon_small">@drawable/ic_lock_black_18dp</item>
<item name="menu_lock_icon_small_received">@drawable/ic_lock_black_18dp</item>
<item name="menu_trash_icon">@drawable/ic_delete_white_24dp</item>
<item name="menu_selectall_icon">@drawable/ic_select_all_white_24dp</item>
@ -199,9 +187,6 @@
<item name="share_list_item_divider">@drawable/share_list_divider_shape_dark</item>
<item name="conversation_group_member_name">#99ffffff</item>
<item name="conversation_sent_text_primary_color">#ffffffff</item>
<item name="conversation_sent_text_secondary_color">#aaeeeeee</item>
<item name="conversation_sent_text_indicator_tab_color">#99ffffff</item>
<item name="conversation_received_text_primary_color">#ffeeeeee</item>
<item name="conversation_received_text_secondary_color">#99eeeeee</item>
@ -211,20 +196,11 @@
<item name="conversation_selection_header_text">#66eeeeee</item>
<item name="conversation_item_background">@drawable/conversation_item_background_dark</item>
<item name="conversation_item_received_background">@color/conversation_item_received_background_dark</item>
<item name="conversation_item_sent_background">@color/conversation_item_sent_background_dark</item>
<item name="conversation_item_sent_push_background">@color/conversation_item_sent_push_background_dark</item>
<item name="conversation_item_sent_pending_background">@color/conversation_item_sent_pending_background_dark</item>
<item name="conversation_item_sent_push_pending_background">@color/conversation_item_sent_push_pending_background_dark</item>
<item name="conversation_item_bubble_background">#ff333333</item>
<item name="conversation_item_sent_text_primary_color">#ffffffff</item>
<item name="conversation_item_sent_text_secondary_color">#aaeeeeee</item>
<item name="conversation_item_sent_text_indicator_tab_color">#99ffffff</item>
<item name="conversation_item_sent_indicator_text_background">@drawable/conversation_item_sent_indicator_text_shape_dark</item>
<item name="conversation_item_shadow">@color/conversation_item_received_shadow_dark</item>
<item name="conversation_item_mms_pending_mask">#99000000</item>
<item name="triangle_tick_incoming">@drawable/triangle_tick_incoming_dark</item>
<item name="triangle_tick_outgoing_sent_sms">@drawable/triangle_tick_outgoing_sent_sms_dark</item>
<item name="triangle_tick_outgoing_sent_push">@drawable/triangle_tick_outgoing_sent_push_dark</item>
<item name="triangle_tick_outgoing_pending_sms">@drawable/triangle_tick_outgoing_pending_sms_dark</item>
<item name="triangle_tick_outgoing_pending_push">@drawable/triangle_tick_outgoing_pending_push_dark</item>
<item name="dialog_info_icon">@drawable/ic_info_outline_dark</item>
<item name="dialog_alert_icon">@drawable/ic_warning_dark</item>
@ -239,9 +215,9 @@
<item name="fab_color">@color/textsecure_primary_dark</item>
<item name="lower_right_divet">@drawable/divet_lower_right_light</item>
<item name="conversation_background">#22ffffff</item>
<item name="conversation_editor_background">#22ffffff</item>
<item name="conversation_editor_text_color">#ffeeeeee</item>
<item name="conversation_delivery_delivered">@drawable/ic_delivery_delivered_dark</item>
<item name="conversation_transport_sms_indicator">@drawable/ic_send_sms_insecure_dark</item>
<item name="conversation_transport_push_indicator">@drawable/ic_send_push</item>
<item name="conversation_transport_popup_background">@color/black</item>

View File

@ -21,11 +21,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.PorterDuff;
import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
@ -36,7 +40,6 @@ import com.afollestad.materialdialogs.AlertDialogWrapper;
import org.thoughtcrime.securesms.ConversationFragment.SelectionClickListener;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.BubbleContainer;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
@ -82,12 +85,14 @@ public class ConversationItem extends LinearLayout {
private TextView indicatorText;
private TextView groupStatusText;
private ImageView secureImage;
private ImageView failedImage;
private AvatarImageView contactPhoto;
private ImageView deliveryImage;
private ImageView pendingIndicator;
private BubbleContainer bubbleContainer;
private ImageView failedIndicator;
private ImageView deliveredIndicator;
private ImageView sentIndicator;
private View pendingIndicator;
private ImageView pendingApprovalIndicator;
private StatusManager statusManager;
private Set<MessageRecord> batchSelected;
private SelectionClickListener selectionClickListener;
private ThumbnailView mediaThumbnail;
@ -113,20 +118,28 @@ public class ConversationItem extends LinearLayout {
protected void onFinishInflate() {
super.onFinishInflate();
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
this.secureImage = (ImageView)findViewById(R.id.sms_secure_indicator);
this.failedImage = (ImageView)findViewById(R.id.sms_failed_indicator);
this.mmsDownloadButton = (Button) findViewById(R.id.mms_download_button);
this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading);
this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo);
this.deliveryImage = (ImageView)findViewById(R.id.delivered_indicator);
this.bodyBubble = findViewById(R.id.body_bubble);
this.pendingIndicator = (ImageView)findViewById(R.id.pending_approval_indicator);
this.bubbleContainer = (BubbleContainer)findViewById(R.id.bubble);
this.mediaThumbnail = (ThumbnailView)findViewById(R.id.image_view);
ViewGroup pendingIndicatorStub = (ViewGroup) findViewById(R.id.pending_indicator_stub);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (Build.VERSION.SDK_INT >= 11) inflater.inflate(R.layout.conversation_item_pending_v11, pendingIndicatorStub, true);
else inflater.inflate(R.layout.conversation_item_pending, pendingIndicatorStub, true);
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
this.secureImage = (ImageView) findViewById(R.id.secure_indicator);
this.failedIndicator = (ImageView) findViewById(R.id.sms_failed_indicator);
this.mmsDownloadButton = (Button) findViewById(R.id.mms_download_button);
this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading);
this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo);
this.deliveredIndicator = (ImageView) findViewById(R.id.delivered_indicator);
this.sentIndicator = (ImageView) findViewById(R.id.sent_indicator);
this.bodyBubble = findViewById(R.id.body_bubble);
this.pendingApprovalIndicator = (ImageView) findViewById(R.id.pending_approval_indicator);
this.pendingIndicator = findViewById(R.id.pending_indicator);
this.mediaThumbnail = (ThumbnailView) findViewById(R.id.image_view);
this.statusManager = new StatusManager(pendingIndicator, sentIndicator, deliveredIndicator, failedIndicator, pendingApprovalIndicator);
setOnClickListener(clickListener);
if (mmsDownloadButton != null) mmsDownloadButton.setOnClickListener(mmsDownloadClickListener);
@ -175,33 +188,12 @@ public class ConversationItem extends LinearLayout {
/// MessageRecord Attribute Parsers
private void setBubbleState(MessageRecord messageRecord) {
final int transportationState;
if ((messageRecord.isPending() || messageRecord.isFailed()) &&
pushDestination &&
!messageRecord.isForcedSms())
{
transportationState = BubbleContainer.TRANSPORT_STATE_PUSH_PENDING;
} else if (messageRecord.isPending() ||
messageRecord.isFailed() ||
messageRecord.isPendingInsecureSmsFallback())
{
transportationState = BubbleContainer.TRANSPORT_STATE_SMS_PENDING;
} else if (messageRecord.isPush()) {
transportationState = BubbleContainer.TRANSPORT_STATE_PUSH_SENT;
} else {
transportationState = BubbleContainer.TRANSPORT_STATE_SMS_SENT;
}
int[] attributes = new int[]{R.attr.conversation_item_bubble_background};
TypedArray colors = context.obtainStyledAttributes(attributes);
final int mediaCaptionState;
if (!hasMedia(messageRecord)) {
mediaCaptionState = BubbleContainer.MEDIA_STATE_NO_MEDIA;
} else if (isCaptionlessMms(messageRecord)) {
mediaCaptionState = BubbleContainer.MEDIA_STATE_CAPTIONLESS;
} else {
mediaCaptionState = BubbleContainer.MEDIA_STATE_CAPTIONED;
}
bodyBubble.getBackground().setColorFilter(colors.getColor(0, 0xFFFFFF), PorterDuff.Mode.SRC_ATOP);
bubbleContainer.setState(transportationState, mediaCaptionState);
colors.recycle();
}
private void setSelectionBackgroundDrawables(MessageRecord messageRecord) {
@ -252,9 +244,18 @@ public class ConversationItem extends LinearLayout {
private void setMediaAttributes(MessageRecord messageRecord) {
if (messageRecord.isMmsNotification()) {
mediaThumbnail.setVisibility(View.GONE);
bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
setNotificationMmsAttributes((NotificationMmsMessageRecord) messageRecord);
} else if (messageRecord.isMms()) {
resolveMedia((MediaMmsMessageRecord) messageRecord);
} else if (hasMedia(messageRecord)) {
mediaThumbnail.setVisibility(View.VISIBLE);
mediaThumbnail.setImageResource(masterSecret, messageRecord.getId(),
messageRecord.getDateReceived(),
((MediaMmsMessageRecord)messageRecord).getSlideDeckFuture());
bodyText.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
} else {
mediaThumbnail.setVisibility(View.GONE);
bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
@ -265,32 +266,29 @@ public class ConversationItem extends LinearLayout {
}
private void setStatusIcons(MessageRecord messageRecord) {
failedImage.setVisibility(messageRecord.isFailed() ? View.VISIBLE : View.GONE);
if (messageRecord.isOutgoing()) pendingIndicator.setVisibility(View.GONE);
if (messageRecord.isOutgoing()) indicatorText.setVisibility(View.GONE);
mmsDownloadButton.setVisibility(View.GONE);
mmsDownloadingLabel.setVisibility(View.GONE);
indicatorText.setVisibility(View.GONE);
secureImage.setVisibility(messageRecord.isSecure() ? View.VISIBLE : View.GONE);
bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isKeyExchange() ? R.drawable.ic_menu_login : 0, 0);
deliveryImage.setVisibility(!messageRecord.isKeyExchange() && messageRecord.isDelivered() ? View.VISIBLE : View.GONE);
mmsDownloadButton.setVisibility(View.GONE);
mmsDownloadingLabel.setVisibility(View.GONE);
if (messageRecord.isFailed()) setFailedStatusIcons();
else if (messageRecord.isPendingInsecureSmsFallback()) setFallbackStatusIcons();
else if (messageRecord.isPending()) dateText.setText(" ··· ");
else setSentStatusIcons();
}
private void setSentStatusIcons() {
final long timestamp;
if (messageRecord.isPush()) timestamp = messageRecord.getDateSent();
else timestamp = messageRecord.getDateReceived();
dateText.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), locale, timestamp));
if (messageRecord.isFailed()) setFailedStatusIcons();
else if (messageRecord.isPendingInsecureSmsFallback()) setFallbackStatusIcons();
else if (messageRecord.isPending()) statusManager.displayPending();
else if (messageRecord.isDelivered()) statusManager.displayDelivered();
else statusManager.displaySent();
}
private void setFailedStatusIcons() {
statusManager.displayFailed();
dateText.setText(R.string.ConversationItem_error_not_delivered);
if (indicatorText != null) {
indicatorText.setText(R.string.ConversationItem_click_for_details);
@ -299,7 +297,7 @@ public class ConversationItem extends LinearLayout {
}
private void setFallbackStatusIcons() {
pendingIndicator.setVisibility(View.VISIBLE);
statusManager.displayPendingApproval();
indicatorText.setVisibility(View.VISIBLE);
indicatorText.setText(R.string.ConversationItem_click_to_approve_unencrypted);
}
@ -307,7 +305,7 @@ public class ConversationItem extends LinearLayout {
private void setMinimumWidth() {
if (indicatorText != null && indicatorText.getVisibility() == View.VISIBLE && indicatorText.getText() != null) {
final float density = getResources().getDisplayMetrics().density;
bodyBubble.setMinimumWidth(indicatorText.getText().length() * (int) (6.5 * density));
bodyBubble.setMinimumWidth(indicatorText.getText().length() * (int) (6.5 * density) + (int) (22.0 * density));
} else {
bodyBubble.setMinimumWidth(0);
}
@ -357,14 +355,6 @@ public class ConversationItem extends LinearLayout {
}
}
private void resolveMedia(MediaMmsMessageRecord messageRecord) {
if (hasMedia(messageRecord)) {
mediaThumbnail.setImageResource(masterSecret, messageRecord.getId(),
messageRecord.getDateReceived(),
messageRecord.getSlideDeckFuture());
}
}
/// Helper Methods
private void setContactPhotoForRecipient(final Recipient recipient) {
@ -538,4 +528,73 @@ public class ConversationItem extends LinearLayout {
});
builder.show();
}
private static class StatusManager {
private final View pendingIndicator;
private final View sentIndicator;
private final View deliveredIndicator;
private final View failedIndicator;
private final View approvalIndicator;
public StatusManager(View pendingIndicator, View sentIndicator,
View deliveredIndicator, View failedIndicator,
View approvalIndicator)
{
this.pendingIndicator = pendingIndicator;
this.sentIndicator = sentIndicator;
this.deliveredIndicator = deliveredIndicator;
this.failedIndicator = failedIndicator;
this.approvalIndicator = approvalIndicator;
}
public void displayFailed() {
pendingIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.VISIBLE);
}
public void displayPendingApproval() {
pendingIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.VISIBLE);
}
public void displayPending() {
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
pendingIndicator.setVisibility(View.VISIBLE);
}
public void displaySent() {
pendingIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.VISIBLE);
}
public void displayDelivered() {
pendingIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.VISIBLE);
}
}
}

View File

@ -1,168 +0,0 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION_CODES;
import android.support.annotation.IntDef;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ResUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
public abstract class BubbleContainer extends RelativeLayout {
@SuppressWarnings("unused")
private static final String TAG = BubbleContainer.class.getSimpleName();
public static final int TRANSPORT_STATE_PUSH_SENT = 0;
public static final int TRANSPORT_STATE_SMS_SENT = 1;
public static final int TRANSPORT_STATE_SMS_PENDING = 2;
public static final int TRANSPORT_STATE_PUSH_PENDING = 3;
public static final int MEDIA_STATE_NO_MEDIA = 0;
public static final int MEDIA_STATE_CAPTIONLESS = 1;
public static final int MEDIA_STATE_CAPTIONED = 2;
@IntDef({TRANSPORT_STATE_PUSH_SENT, TRANSPORT_STATE_PUSH_PENDING, TRANSPORT_STATE_SMS_SENT, TRANSPORT_STATE_SMS_PENDING})
public @interface TransportState {}
@IntDef({MEDIA_STATE_NO_MEDIA, MEDIA_STATE_CAPTIONLESS, MEDIA_STATE_CAPTIONED})
public @interface MediaState {}
private View bodyBubble;
private View triangleTick;
private ThumbnailView media;
private int shadowColor;
private int mmsPendingOverlayColor;
public BubbleContainer(Context context) {
super(context);
initialize();
}
public BubbleContainer(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public BubbleContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize();
}
@TargetApi(VERSION_CODES.LOLLIPOP)
public BubbleContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize();
}
protected abstract void onCreateView();
protected abstract int getForegroundColor(@TransportState int transportState);
protected abstract boolean[] getMessageCorners(@MediaState int mediaState);
protected abstract boolean[] getMediaCorners(@MediaState int mediaState);
protected abstract int getTriangleTickRes(@TransportState int transportState);
protected void initialize() {
onCreateView();
this.bodyBubble = findViewById(R.id.body_bubble );
this.triangleTick = findViewById(R.id.triangle_tick);
this.media = (ThumbnailView) findViewById(R.id.image_view);
this.shadowColor = ResUtil.getColor(getContext(), R.attr.conversation_item_shadow);
this.mmsPendingOverlayColor = ResUtil.getColor(getContext(), R.attr.conversation_item_mms_pending_mask);
}
public void setState(@TransportState int transportState, @MediaState int mediaState) {
updateBodyBubble(transportState, mediaState);
if (isMediaPresent(mediaState)) {
updateMediaBubble(transportState, mediaState);
}
setMediaVisibility(mediaState);
setAlignment(mediaState);
setMediaPendingMask(transportState);
}
private void updateBodyBubble(@TransportState int transportState, @MediaState int mediaState) {
final boolean hasShadow = mediaState == MEDIA_STATE_CAPTIONED || mediaState == MEDIA_STATE_NO_MEDIA;
final BubbleDrawableBuilder builder = new BubbleDrawableBuilder();
final int color = getForegroundColor(transportState);
final Drawable bodyDrawable = builder.setColor(color)
.setShadowColor(shadowColor)
.setCorners(getMessageCorners(mediaState))
.setHasShadow(hasShadow)
.create(getContext());
ViewUtil.setBackgroundSavingPadding(triangleTick, getTriangleTickRes(transportState));
ViewUtil.setBackgroundSavingPadding(bodyBubble, bodyDrawable);
}
private void updateMediaBubble(@TransportState int transportState, @MediaState int mediaState) {
final int foregroundColor = getForegroundColor(transportState);
final BubbleDrawableBuilder builder = new BubbleDrawableBuilder();
final Drawable mediaDrawable = builder.setColor(foregroundColor)
.setShadowColor(shadowColor)
.setCorners(getMediaCorners(mediaState))
.setHasShadow(false)
.create(getContext());
ViewUtil.setBackgroundSavingPadding(media, mediaDrawable);
media.setBorderColor(foregroundColor);
}
private void setMediaVisibility(@MediaState int mediaState) {
if (!isMediaPresent(mediaState)) media.setVisibility(View.GONE);
else media.setVisibility(View.VISIBLE);
}
private void setMediaPendingMask(@TransportState int transportState) {
if (isPending(transportState)) {
media.setForeground(new ColorDrawable(mmsPendingOverlayColor));
} else {
media.setForeground(new ColorDrawable(Color.TRANSPARENT));
}
}
private void setAlignment(@MediaState int mediaState) {
RelativeLayout.LayoutParams parentParams = (RelativeLayout.LayoutParams) bodyBubble.getLayoutParams();
if (mediaState == MEDIA_STATE_CAPTIONLESS) {
parentParams.addRule(RelativeLayout.BELOW, 0);
parentParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.thumbnail_container);
} else if (mediaState == MEDIA_STATE_CAPTIONED) {
parentParams.addRule(RelativeLayout.BELOW, R.id.thumbnail_container);
parentParams.addRule(RelativeLayout.ALIGN_BOTTOM, 0);
} else {
parentParams.addRule(RelativeLayout.BELOW, 0);
parentParams.addRule(RelativeLayout.ALIGN_BOTTOM, 0);
}
bodyBubble.setLayoutParams(parentParams);
}
private boolean isMediaPresent(@MediaState int mediaState) {
return mediaState != MEDIA_STATE_NO_MEDIA;
}
private boolean isPending(@TransportState int transportState) {
return transportState == TRANSPORT_STATE_PUSH_PENDING || transportState == TRANSPORT_STATE_SMS_PENDING;
}
}

View File

@ -1,87 +0,0 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ResUtil;
public class IncomingBubbleContainer extends BubbleContainer {
private static final String TAG = IncomingBubbleContainer.class.getSimpleName();
private static final boolean[] CORNERS_MESSAGE_CAPTIONED = new boolean[]{false, true, true, true };
private static final boolean[] CORNERS_MEDIA_CAPTIONED = new boolean[]{true, true, true, false};
private static final boolean[] CORNERS_ROUNDED = new boolean[]{true, true, true, true };
private int foregroundColor;
private int triangleTickRes;
@SuppressWarnings("UnusedDeclaration")
public IncomingBubbleContainer(Context context) {
super(context);
}
@SuppressWarnings("UnusedDeclaration")
public IncomingBubbleContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
@SuppressWarnings("UnusedDeclaration")
public IncomingBubbleContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@SuppressWarnings("UnusedDeclaration")
public IncomingBubbleContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onCreateView() {
Log.w(TAG, "onCreateView()");
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.conversation_bubble_incoming, this, true);
this.foregroundColor = ResUtil.getColor(getContext(), R.attr.conversation_item_received_background);
this.triangleTickRes = ResUtil.getDrawableRes(getContext(), R.attr.triangle_tick_incoming);
}
@Override
protected int getForegroundColor(@TransportState int transportState) {
return foregroundColor;
}
@Override
protected boolean[] getMessageCorners(@MediaState int mediaState) {
return mediaState == MEDIA_STATE_CAPTIONED ? CORNERS_MESSAGE_CAPTIONED : CORNERS_ROUNDED;
}
@Override
protected boolean[] getMediaCorners(@MediaState int mediaState) {
return mediaState == MEDIA_STATE_CAPTIONED ? CORNERS_MEDIA_CAPTIONED : CORNERS_ROUNDED;
}
@Override
protected int getTriangleTickRes(@TransportState int transportState) {
return triangleTickRes;
}
}

View File

@ -1,105 +0,0 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import org.thoughtcrime.securesms.R;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class OutgoingBubbleContainer extends BubbleContainer {
private static final boolean[] CORNERS_MESSAGE_CAPTIONED = new boolean[]{true, false, true, true};
private static final boolean[] CORNERS_MEDIA_CAPTIONED = new boolean[]{true, true, false, true};
private static final boolean[] CORNERS_ROUNDED = new boolean[]{true, true, true, true};
private static final int[] TRANSPORT_STYLE_ATTRIBUTES = new int[]{R.attr.conversation_item_sent_push_background,
R.attr.conversation_item_sent_background,
R.attr.conversation_item_sent_pending_background,
R.attr.conversation_item_sent_push_pending_background};
private static final int[] TRIANGLE_TICK_ATTRIBUTES = new int[]{R.attr.triangle_tick_outgoing_sent_push,
R.attr.triangle_tick_outgoing_sent_sms,
R.attr.triangle_tick_outgoing_pending_sms,
R.attr.triangle_tick_outgoing_pending_push};
private static final SparseIntArray TRANSPORT_STYLE_MAP = new SparseIntArray(TRANSPORT_STYLE_ATTRIBUTES.length) {{
put(TRANSPORT_STATE_PUSH_SENT, 0);
put(TRANSPORT_STATE_SMS_SENT, 1);
put(TRANSPORT_STATE_SMS_PENDING, 2);
put(TRANSPORT_STATE_PUSH_PENDING, 3);
}};
private TypedArray styledDrawables;
private TypedArray triangleDrawables;
@SuppressWarnings("UnusedDeclaration")
public OutgoingBubbleContainer(Context context) {
super(context);
}
@SuppressWarnings("UnusedDeclaration")
public OutgoingBubbleContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
@SuppressWarnings("UnusedDeclaration")
public OutgoingBubbleContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@SuppressWarnings("UnusedDeclaration")
public OutgoingBubbleContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onCreateView() {
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.conversation_bubble_outgoing, this, true);
this.styledDrawables = getContext().obtainStyledAttributes(TRANSPORT_STYLE_ATTRIBUTES);
this.triangleDrawables = getContext().obtainStyledAttributes(TRIANGLE_TICK_ATTRIBUTES );
}
@Override
protected int getForegroundColor(@TransportState int transportState) {
return styledDrawables.getColor(TRANSPORT_STYLE_MAP.get(transportState), -1);
}
@Override
protected boolean[] getMessageCorners(@MediaState int mediaState) {
return mediaState == MEDIA_STATE_CAPTIONED ? CORNERS_MESSAGE_CAPTIONED : CORNERS_ROUNDED;
}
@Override
protected boolean[] getMediaCorners(@MediaState int mediaState) {
return mediaState == MEDIA_STATE_CAPTIONED ? CORNERS_MEDIA_CAPTIONED : CORNERS_ROUNDED;
}
@Override
protected int getTriangleTickRes(@TransportState int transportState) {
return triangleDrawables.getResourceId(TRANSPORT_STYLE_MAP.get(transportState), -1);
}
}

View File

@ -14,11 +14,14 @@ import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import com.bumptech.glide.GenericRequestBuilder;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.makeramen.roundedimageview.RoundedImageView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterSecret;
@ -32,7 +35,7 @@ import org.thoughtcrime.securesms.util.Util;
import ws.com.google.android.mms.pdu.PduPart;
public class ThumbnailView extends ForegroundImageView {
public class ThumbnailView extends RoundedImageView {
private ListenableFutureTask<SlideDeck> slideDeckFuture = null;
private SlideDeckListener slideDeckListener = null;
@ -96,6 +99,13 @@ public class ThumbnailView extends ForegroundImageView {
if (isContextValid()) Glide.clear(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View dv = ((Activity) this.getContext()).getWindow().getDecorView();
int size = Math.min(dv.getWidth(), dv.getHeight()) * 55 / 100;
setMeasuredDimension(size, size);
}
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
private boolean isContextValid() {
return !(getContext() instanceof Activity) ||
@ -238,4 +248,5 @@ public class ThumbnailView extends ForegroundImageView {
return false;
}
}
}

View File

@ -50,7 +50,7 @@ public class SmsMessageRecord extends MessageRecord {
int status, List<IdentityKeyMismatch> mismatches)
{
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, receiptCount, getGenericDeliveryStatus(status), type,
dateSent, dateReceived, threadId, getGenericDeliveryStatus(status), receiptCount, type,
mismatches, new LinkedList<NetworkFailure>());
}