parent
a4e18c515c
commit
4185006147
75 changed files with 1384 additions and 1001 deletions
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_received_shadow_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_received_background_light" />
|
||||
<!--stroke android:width="0.5dp" android:color="#03000000" /-->
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_received_shadow_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_received_background_dark" />
|
||||
<!--stroke android:width="0.5dp" android:color="#03000000" /-->
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -4,14 +4,14 @@
|
|||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#09000000" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:radius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<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" />
|
||||
<corners android:bottomLeftRadius="@dimen/conversation_item_corner_radius" android:bottomRightRadius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:bottomLeftRadius="@dimen/message_bubble_corner_radius" android:bottomRightRadius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#09000000" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:radius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<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" />
|
||||
<corners android:bottomLeftRadius="@dimen/conversation_item_corner_radius" android:bottomRightRadius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:bottomLeftRadius="@dimen/message_bubble_corner_radius" android:bottomRightRadius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_pending_background_light" />
|
||||
<!--stroke android:width="0.5dp" android:color="#03000000" /-->
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_pending_background_dark" />
|
||||
<!--stroke android:width="0.5dp" android:color="#03000000" /-->
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape>
|
||||
<solid android:color="@color/conversation_item_sent_push_pending_background_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_push_pending_background_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_push_background_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_push_background_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate 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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_background_light" />
|
||||
<!--stroke android:width="0.5dp" android:color="#03000000" /-->
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_item_sent_shadow_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/conversation_item_sent_background_dark" />
|
||||
<!--stroke android:width="0.5dp" android:color="#03000000" /-->
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<rotate
|
||||
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>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -4,14 +4,14 @@
|
|||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/import_export_item_background_shadow_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:radius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<item android:bottom="@dimen/message_bubble_shadow_distance">
|
||||
<shape>
|
||||
<solid android:color="@color/import_export_item_background_dark" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:radius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/import_export_item_background_shadow_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:radius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="@dimen/conversation_item_drop_shadow_dist">
|
||||
<item android:bottom="@dimen/message_bubble_shadow_distance">
|
||||
<shape>
|
||||
<solid android:color="@color/import_export_item_background_light" />
|
||||
<corners android:radius="@dimen/conversation_item_corner_radius" />
|
||||
<corners android:radius="@dimen/message_bubble_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
|
|
13
res/drawable/triangle_tick_incoming_dark.xml
Normal file
13
res/drawable/triangle_tick_incoming_dark.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_incoming_light.xml
Normal file
13
res/drawable/triangle_tick_incoming_light.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_pending_push_dark.xml
Normal file
13
res/drawable/triangle_tick_outgoing_pending_push_dark.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_pending_push_light.xml
Normal file
13
res/drawable/triangle_tick_outgoing_pending_push_light.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_pending_sms_dark.xml
Normal file
13
res/drawable/triangle_tick_outgoing_pending_sms_dark.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_pending_sms_light.xml
Normal file
13
res/drawable/triangle_tick_outgoing_pending_sms_light.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_sent_push_dark.xml
Normal file
13
res/drawable/triangle_tick_outgoing_sent_push_dark.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_sent_push_light.xml
Normal file
13
res/drawable/triangle_tick_outgoing_sent_push_light.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_sent_sms_dark.xml
Normal file
13
res/drawable/triangle_tick_outgoing_sent_sms_dark.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
13
res/drawable/triangle_tick_outgoing_sent_sms_light.xml
Normal file
13
res/drawable/triangle_tick_outgoing_sent_sms_light.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
114
res/layout/conversation_bubble_incoming.xml
Normal file
114
res/layout/conversation_bubble_incoming.xml
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?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" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.ForegroundImageView
|
||||
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_toRightOf="@id/triangle_tick"
|
||||
android:layout_toEndOf="@id/triangle_tick"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerCrop"
|
||||
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 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/image_view"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView 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>
|
133
res/layout/conversation_bubble_outgoing.xml
Normal file
133
res/layout/conversation_bubble_outgoing.xml
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?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" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.ForegroundImageView
|
||||
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_toLeftOf="@id/triangle_tick"
|
||||
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 android:id="@+id/body_bubble"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/image_view"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignBottom="@id/image_view"
|
||||
android:paddingRight="10dip"
|
||||
android:paddingLeft="10dip"
|
||||
android:layout_marginLeft="50dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView 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>
|
|
@ -6,28 +6,27 @@
|
|||
android:orientation="vertical"
|
||||
android:background="?conversation_item_background"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<TextView android:id="@+id/group_message_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:textSize="13sp"
|
||||
android:textColor="?attr/conversation_group_member_name"
|
||||
android:visibility="gone" />
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:textSize="13sp"
|
||||
android:textColor="?attr/conversation_group_member_name"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginLeft="9dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginRight="0dp"
|
||||
android:orientation="horizontal">
|
||||
<RelativeLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginLeft="9dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginRight="0dp">
|
||||
|
||||
<com.makeramen.RoundedImageView
|
||||
<org.thoughtcrime.securesms.components.ForegroundImageView
|
||||
android:id="@+id/contact_photo"
|
||||
android:foreground="@drawable/contact_photo_background"
|
||||
android:layout_width="40dp"
|
||||
|
@ -38,118 +37,12 @@
|
|||
android:cropToPadding="true"
|
||||
android:contentDescription="@string/conversation_item_received__contact_photo_description"
|
||||
android:scaleType="centerCrop" />
|
||||
<View android:id="@+id/triangle_tick"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_alignRight="@id/contact_photo"
|
||||
android:background="?conversation_item_received_triangle_background" />
|
||||
|
||||
<LinearLayout android:id="@+id/conversation_item_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/triangle_tick"
|
||||
android:background="?conversation_item_received_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/conversation_item_body"
|
||||
<org.thoughtcrime.securesms.components.IncomingBubbleContainer
|
||||
android:id="@+id/bubble"
|
||||
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" />
|
||||
|
||||
<FrameLayout android:id="@+id/mms_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView android:id="@+id/image_view"
|
||||
android:layout_width="230dip"
|
||||
android:layout_height="174dip"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerInside"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/conversation_item__mms_image_description"
|
||||
android:visibility="gone" />
|
||||
<ImageButton android:id="@+id/play_slideshow_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/mms_play_btn"
|
||||
android:contentDescription="@string/conversation_item__play_button_description"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
<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="fill_parent"
|
||||
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>
|
||||
android:layout_marginLeft="29dp" />
|
||||
|
||||
<LinearLayout android:id="@+id/indicators_parent"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<org.thoughtcrime.securesms.ConversationItem
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/conversation_item"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -10,7 +11,6 @@
|
|||
|
||||
<RelativeLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
|
@ -46,145 +46,15 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:id="@+id/conversation_item_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?conversation_item_sent_push_background"
|
||||
android:paddingRight="10dip"
|
||||
android:paddingLeft="10dip"
|
||||
android:layout_marginLeft="50dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/conversation_item_body"
|
||||
android:autoLink="all"
|
||||
<org.thoughtcrime.securesms.components.OutgoingBubbleContainer
|
||||
android:id="@+id/bubble"
|
||||
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="Lorem ipsum mango dolor coconut papaya" />
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/mms_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view"
|
||||
android:layout_width="230dip"
|
||||
android:layout_height="174dip"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerInside"
|
||||
android:adjustViewBounds="true"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/conversation_item__mms_image_description"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/play_slideshow_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/mms_play_btn"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/conversation_item__play_button_description"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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="fill_parent"
|
||||
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" />
|
||||
|
||||
<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>
|
||||
|
||||
<View android:id="@+id/triangle_tick"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="?conversation_item_sent_triangle_background" />
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView android:id="@+id/indicator_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/conversation_item_parent"
|
||||
android:layout_below="@id/bubble"
|
||||
android:layout_alignParentRight="true"
|
||||
android:paddingRight="5dip"
|
||||
android:paddingLeft="5dip"
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/media_preview_activity__image_content_description" />
|
||||
<org.thoughtcrime.securesms.components.ForegroundImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="#11ffffff"
|
||||
android:contentDescription="@string/media_preview_activity__image_content_description" />
|
||||
|
||||
</org.thoughtcrime.securesms.components.SquareLinearLayout>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/gray95">
|
||||
|
@ -12,16 +11,6 @@
|
|||
android:contentDescription="@string/media_preview_activity__image_content_description"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView android:id="@+id/loading_indicator"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="···"
|
||||
android:textSize="30sp"
|
||||
android:textColor="@color/gray10"
|
||||
android:visibility="gone"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView android:id="@+id/error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -39,18 +39,22 @@
|
|||
|
||||
<attr name="conversation_item_background" format="reference"/>
|
||||
<attr name="conversation_item_received_background" format="reference" />
|
||||
<attr name="conversation_item_received_triangle_background" format="reference" />
|
||||
<attr name="conversation_item_sent_background" format="reference" />
|
||||
<attr name="conversation_item_sent_triangle_background" format="reference" />
|
||||
<attr name="conversation_item_sent_pending_background" format="reference" />
|
||||
<attr name="conversation_item_sent_pending_triangle_background" format="reference" />
|
||||
<attr name="conversation_item_sent_push_background" format="reference" />
|
||||
<attr name="conversation_item_sent_push_triangle_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_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" />
|
||||
<attr name="conversation_item_sent_push_pending_background" format="reference" />
|
||||
<attr name="conversation_item_sent_push_pending_triangle_background" format="reference" />
|
||||
|
||||
<attr name="conversation_icon_attach_audio" format="reference"/>
|
||||
<attr name="conversation_icon_attach_video" format="reference" />
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
<color name="conversation_item_sent_pending_background_light">#5564A926</color>
|
||||
<color name="conversation_item_sent_pending_background_dark">#55284e0a</color>
|
||||
<color name="conversation_item_sent_push_background_light">#ff2090ea</color>
|
||||
<color name="conversation_item_sent_push_background_dark">#ff213b77</color>
|
||||
<color name="conversation_item_sent_push_pending_background_light">#ff528ff2</color>
|
||||
<color name="conversation_item_sent_push_pending_background_dark">#55213b77</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>
|
||||
|
|
|
@ -9,13 +9,18 @@
|
|||
<dimen name="transport_selection_popup_width">200sp</dimen>
|
||||
<dimen name="transport_selection_popup_xoff">0dp</dimen>
|
||||
<dimen name="transport_selection_popup_yoff">1dp</dimen>
|
||||
<dimen name="conversation_item_corner_radius">4dp</dimen>
|
||||
<dimen name="conversation_item_drop_shadow_dist">1.5dp</dimen>
|
||||
<dimen name="contact_selection_photo_size">50dp</dimen>
|
||||
<dimen name="thumbnail_max_size">230dp</dimen>
|
||||
<dimen name="preference_fragment_padding_side">8dp</dimen>
|
||||
<dimen name="conversation_activity_compose_padding">12dp</dimen>
|
||||
|
||||
<dimen name="message_bubble_end_padding">50dp</dimen>
|
||||
<dimen name="message_bubble_corner_radius">4dp</dimen>
|
||||
<dimen name="message_bubble_shadow_distance">1.5dp</dimen>
|
||||
<dimen name="media_bubble_height">210dp</dimen>
|
||||
<dimen name="media_bubble_border_width">3dp</dimen>
|
||||
|
||||
|
||||
<integer name="media_overview_cols">3</integer>
|
||||
<dimen name="message_details_table_row_pad">10dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -479,6 +479,7 @@
|
|||
<string name="conversation_activity__attachment_thumbnail">Attachment Thumbnail</string>
|
||||
|
||||
<!-- conversation_item -->
|
||||
<string name="conversation_item__mms_downloading_description">Media message downloading</string>
|
||||
<string name="conversation_item__mms_image_description">Media message</string>
|
||||
<string name="conversation_item__play_button_description">Play button</string>
|
||||
<string name="conversation_item__secure_message_description">Secure message</string>
|
||||
|
|
|
@ -55,20 +55,23 @@
|
|||
<item name="conversation_keyboard_toggle">@drawable/ic_ime_dark</item>
|
||||
|
||||
<item name="conversation_item_background">@drawable/conversation_item_background</item>
|
||||
<item name="conversation_item_received_background">@drawable/conversation_item_received_shape</item>
|
||||
<item name="conversation_item_received_triangle_background">@drawable/conversation_item_received_triangle_shape</item>
|
||||
<item name="conversation_item_sent_background">@drawable/conversation_item_sent_shape</item>
|
||||
<item name="conversation_item_sent_triangle_background">@drawable/conversation_item_sent_triangle_shape</item>
|
||||
<item name="conversation_item_sent_push_background">@drawable/conversation_item_sent_push_shape</item>
|
||||
<item name="conversation_item_sent_push_triangle_background">@drawable/conversation_item_sent_push_triangle_shape</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_dialog_info_light</item>
|
||||
<item name="dialog_alert_icon">@drawable/ic_dialog_alert_light</item>
|
||||
<item name="conversation_item_sent_pending_background">@drawable/conversation_item_sent_pending_shape</item>
|
||||
<item name="conversation_item_sent_pending_triangle_background">@drawable/conversation_item_sent_pending_triangle_shape</item>
|
||||
<item name="conversation_item_sent_push_pending_background">@drawable/conversation_item_sent_push_pending_shape</item>
|
||||
<item name="conversation_item_sent_push_pending_triangle_background">@drawable/conversation_item_sent_push_pending_triangle_shape</item>
|
||||
|
||||
<item name="import_export_item_background_color">@color/import_export_item_background_light</item>
|
||||
<item name="import_export_item_background_shadow_color">@color/import_export_item_background_shadow_light</item>
|
||||
|
@ -142,19 +145,22 @@
|
|||
<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">@drawable/conversation_item_received_shape_dark</item>
|
||||
<item name="conversation_item_received_triangle_background">@drawable/conversation_item_received_triangle_shape_dark</item>
|
||||
<item name="conversation_item_sent_background">@drawable/conversation_item_sent_shape_dark</item>
|
||||
<item name="conversation_item_sent_triangle_background">@drawable/conversation_item_sent_triangle_shape_dark</item>
|
||||
<item name="conversation_item_sent_push_background">@drawable/conversation_item_sent_push_shape_dark</item>
|
||||
<item name="conversation_item_sent_push_triangle_background">@drawable/conversation_item_sent_push_triangle_shape_dark</item>
|
||||
<item name="conversation_item_sent_indicator_text_background">@drawable/conversation_item_sent_indicator_text_shape_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_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_dialog_info_dark</item>
|
||||
<item name="dialog_alert_icon">@drawable/ic_dialog_alert_dark</item>
|
||||
<item name="conversation_item_sent_pending_background">@drawable/conversation_item_sent_pending_shape_dark</item>
|
||||
<item name="conversation_item_sent_pending_triangle_background">@drawable/conversation_item_sent_pending_triangle_shape_dark</item>
|
||||
<item name="conversation_item_sent_push_pending_background">@drawable/conversation_item_sent_push_pending_shape_dark</item>
|
||||
<item name="conversation_item_sent_push_pending_triangle_background">@drawable/conversation_item_sent_push_pending_triangle_shape_dark</item>
|
||||
|
||||
<item name="import_export_item_background_color">@color/import_export_item_background_dark</item>
|
||||
<item name="import_export_item_background_shadow_color">@color/import_export_item_background_shadow_dark</item>
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.util.DynamicLanguage;
|
|||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.MemoryCleaner;
|
||||
import org.thoughtcrime.securesms.util.ProgressDialogAsyncTask;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||
import org.whispersystems.textsecure.api.TextSecureAccountManager;
|
||||
|
@ -286,7 +287,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||
public boolean onPreferenceChange(final Preference preference, Object newValue) {
|
||||
if (((CheckBoxPreference)preference).isChecked()) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_info_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_info_icon));
|
||||
builder.setTitle(R.string.ApplicationPreferencesActivity_disable_push_messages);
|
||||
builder.setMessage(R.string.ApplicationPreferencesActivity_this_will_disable_push_messages);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
|
|
|
@ -96,6 +96,7 @@ import org.thoughtcrime.securesms.util.DynamicTheme;
|
|||
import org.thoughtcrime.securesms.util.Emoji;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.MemoryCleaner;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
|
@ -358,7 +359,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||
private void handleAbortSecureSession() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.ConversationActivity_abort_secure_session_confirmation);
|
||||
builder.setIcon(Dialogs.resolveIcon(this, R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(this, R.attr.dialog_alert_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(R.string.ConversationActivity_are_you_sure_that_you_want_to_abort_this_secure_session_question);
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
|
@ -405,7 +406,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(getString(R.string.ConversationActivity_leave_group));
|
||||
builder.setIcon(Dialogs.resolveIcon(this, R.attr.dialog_info_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(this, R.attr.dialog_info_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
|
@ -498,7 +499,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||
private void handleDeleteThread() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.ConversationActivity_delete_thread_confirmation);
|
||||
builder.setIcon(Dialogs.resolveIcon(this, R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(this, R.attr.dialog_alert_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(R.string.ConversationActivity_are_you_sure_that_you_want_to_permanently_delete_this_conversation_question);
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
|
|
|
@ -116,7 +116,6 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re
|
|||
default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter");
|
||||
}
|
||||
|
||||
bindView(view, context, cursor);
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.util.Dialogs;
|
|||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.ProgressDialogAsyncTask;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
|
||||
|
||||
|
@ -192,7 +193,7 @@ public class ConversationFragment extends ListFragment
|
|||
private void handleDeleteMessages(final List<MessageRecord> messageRecords) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setTitle(R.string.ConversationFragment_confirm_message_delete);
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(R.string.ConversationFragment_are_you_sure_you_want_to_permanently_delete_all_selected_messages);
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
|
|
|
@ -23,15 +23,18 @@ import android.content.DialogInterface;
|
|||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Looper;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.ContactsContract.QuickContact;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
|
@ -40,6 +43,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.ConversationFragment.SelectionClickListener;
|
||||
import org.thoughtcrime.securesms.components.ForegroundImageView;
|
||||
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
|
@ -56,11 +60,12 @@ import org.thoughtcrime.securesms.mms.PartAuthority;
|
|||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.components.BubbleContainer;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.Emoji;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -75,57 +80,39 @@ import java.util.Set;
|
|||
public class ConversationItem extends LinearLayout {
|
||||
private final static String TAG = ConversationItem.class.getSimpleName();
|
||||
|
||||
private final int STYLE_ATTRIBUTES[] = new int[]{R.attr.conversation_item_sent_push_background,
|
||||
R.attr.conversation_item_sent_push_triangle_background,
|
||||
R.attr.conversation_item_sent_background,
|
||||
R.attr.conversation_item_sent_triangle_background,
|
||||
R.attr.conversation_item_sent_pending_background,
|
||||
R.attr.conversation_item_sent_pending_triangle_background,
|
||||
R.attr.conversation_item_sent_push_pending_background,
|
||||
R.attr.conversation_item_sent_push_pending_triangle_background};
|
||||
|
||||
private final static int SENT_PUSH = 0;
|
||||
private final static int SENT_PUSH_TRIANGLE = 1;
|
||||
private final static int SENT_SMS = 2;
|
||||
private final static int SENT_SMS_TRIANGLE = 3;
|
||||
private final static int SENT_SMS_PENDING = 4;
|
||||
private final static int SENT_SMS_PENDING_TRIANGLE = 5;
|
||||
private final static int SENT_PUSH_PENDING = 6;
|
||||
private final static int SENT_PUSH_PENDING_TRIANGLE = 7;
|
||||
|
||||
private Handler failedIconHandler;
|
||||
private MessageRecord messageRecord;
|
||||
private MasterSecret masterSecret;
|
||||
private boolean groupThread;
|
||||
private boolean pushDestination;
|
||||
|
||||
private View conversationParent;
|
||||
private TextView bodyText;
|
||||
private TextView dateText;
|
||||
private TextView indicatorText;
|
||||
private TextView groupStatusText;
|
||||
private ImageView secureImage;
|
||||
private ImageView failedImage;
|
||||
private ImageView contactPhoto;
|
||||
private ImageView deliveryImage;
|
||||
private View triangleTick;
|
||||
private ImageView pendingIndicator;
|
||||
private View bodyBubble;
|
||||
private TextView bodyText;
|
||||
private TextView dateText;
|
||||
private TextView indicatorText;
|
||||
private TextView groupStatusText;
|
||||
private ImageView secureImage;
|
||||
private ImageView failedImage;
|
||||
private ImageView contactPhoto;
|
||||
private ImageView deliveryImage;
|
||||
private ImageView pendingIndicator;
|
||||
private BubbleContainer bubbleContainer;
|
||||
|
||||
private Set<MessageRecord> batchSelected;
|
||||
private SelectionClickListener selectionClickListener;
|
||||
private View mmsContainer;
|
||||
private ImageView mmsThumbnail;
|
||||
private Button mmsDownloadButton;
|
||||
private TextView mmsDownloadingLabel;
|
||||
private ListenableFutureTask<SlideDeck> slideDeck;
|
||||
private FutureTaskListener<SlideDeck> slideDeckListener;
|
||||
private TypedArray backgroundDrawables;
|
||||
private Set<MessageRecord> batchSelected;
|
||||
private SelectionClickListener selectionClickListener;
|
||||
private ForegroundImageView mediaThumbnail;
|
||||
private Button mmsDownloadButton;
|
||||
private TextView mmsDownloadingLabel;
|
||||
|
||||
private ListenableFutureTask<SlideDeck> slideDeckFuture;
|
||||
private ListenableFutureTask<Pair<Drawable, Boolean>> thumbnailFuture;
|
||||
private SlideDeckListener slideDeckListener;
|
||||
private ThumbnailListener thumbnailListener;
|
||||
private Handler handler;
|
||||
|
||||
private final MmsDownloadClickListener mmsDownloadClickListener = new MmsDownloadClickListener();
|
||||
private final MmsPreferencesClickListener mmsPreferencesClickListener = new MmsPreferencesClickListener();
|
||||
private final ClickListener clickListener = new ClickListener();
|
||||
private final Handler handler = new Handler();
|
||||
private final Context context;
|
||||
private final Context context;
|
||||
|
||||
public ConversationItem(Context context) {
|
||||
super(context);
|
||||
|
@ -147,20 +134,21 @@ public class ConversationItem extends LinearLayout {
|
|||
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.mmsContainer = findViewById(R.id.mms_view);
|
||||
this.mmsThumbnail = (ImageView)findViewById(R.id.image_view);
|
||||
this.mmsDownloadButton = (Button) findViewById(R.id.mms_download_button);
|
||||
this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading);
|
||||
this.contactPhoto = (ImageView)findViewById(R.id.contact_photo);
|
||||
this.deliveryImage = (ImageView)findViewById(R.id.delivered_indicator);
|
||||
this.conversationParent = findViewById(R.id.conversation_item_parent);
|
||||
this.triangleTick = findViewById(R.id.triangle_tick);
|
||||
this.bodyBubble = findViewById(R.id.body_bubble);
|
||||
this.pendingIndicator = (ImageView)findViewById(R.id.pending_approval_indicator);
|
||||
this.backgroundDrawables = context.obtainStyledAttributes(STYLE_ATTRIBUTES);
|
||||
this.bubbleContainer = (BubbleContainer)findViewById(R.id.bubble);
|
||||
this.mediaThumbnail = (ForegroundImageView)findViewById(R.id.image_view);
|
||||
|
||||
slideDeckListener = new SlideDeckListener();
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
setOnClickListener(clickListener);
|
||||
if (mmsDownloadButton != null) mmsDownloadButton.setOnClickListener(mmsDownloadClickListener);
|
||||
if (mmsThumbnail != null) mmsThumbnail.setOnLongClickListener(new MultiSelectLongClickListener());
|
||||
if (mediaThumbnail != null) mediaThumbnail.setOnLongClickListener(new MultiSelectLongClickListener());
|
||||
}
|
||||
|
||||
public void set(@NonNull MasterSecret masterSecret,
|
||||
|
@ -176,73 +164,65 @@ public class ConversationItem extends LinearLayout {
|
|||
this.groupThread = groupThread;
|
||||
this.pushDestination = pushDestination;
|
||||
|
||||
setConversationBackgroundDrawables(messageRecord);
|
||||
setSelectionBackgroundDrawables(messageRecord);
|
||||
setBodyText(messageRecord);
|
||||
|
||||
if (!messageRecord.isGroupAction()) {
|
||||
if (hasConversationBubble(messageRecord)) {
|
||||
setBubbleState(messageRecord);
|
||||
setStatusIcons(messageRecord);
|
||||
setContactPhoto(messageRecord);
|
||||
setGroupMessageStatus(messageRecord);
|
||||
setEvents(messageRecord);
|
||||
setMinimumWidth();
|
||||
|
||||
if (messageRecord.isMmsNotification()) {
|
||||
setNotificationMmsAttributes((NotificationMmsMessageRecord)messageRecord);
|
||||
} else if (messageRecord.isMms()) {
|
||||
setMediaMmsAttributes((MediaMmsMessageRecord)messageRecord);
|
||||
}
|
||||
setMediaAttributes(messageRecord);
|
||||
}
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
if (slideDeck != null && slideDeckListener != null)
|
||||
slideDeck.removeListener(slideDeckListener);
|
||||
if (slideDeckFuture != null && slideDeckListener != null) {
|
||||
slideDeckFuture.removeListener(slideDeckListener);
|
||||
}
|
||||
|
||||
if (thumbnailFuture != null && thumbnailListener != null) {
|
||||
thumbnailFuture.removeListener(thumbnailListener);
|
||||
}
|
||||
}
|
||||
|
||||
public MessageRecord getMessageRecord() {
|
||||
return messageRecord;
|
||||
}
|
||||
|
||||
public void setHandler(Handler failedIconHandler) {
|
||||
this.failedIconHandler = failedIconHandler;
|
||||
}
|
||||
|
||||
public static void setViewBackgroundWithoutResettingPadding(final View v, final int backgroundResId) {
|
||||
final int paddingBottom = v.getPaddingBottom();
|
||||
final int paddingLeft = v.getPaddingLeft();
|
||||
final int paddingRight = v.getPaddingRight();
|
||||
final int paddingTop = v.getPaddingTop();
|
||||
v.setBackgroundResource(backgroundResId);
|
||||
v.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
}
|
||||
|
||||
/// MessageRecord Attribute Parsers
|
||||
|
||||
private void setConversationBackgroundDrawables(MessageRecord messageRecord) {
|
||||
if (conversationParent != null && backgroundDrawables != null) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
final int background;
|
||||
final int triangleBackground;
|
||||
if ((messageRecord.isPending() || messageRecord.isFailed()) && pushDestination && !messageRecord.isForcedSms()) {
|
||||
background = SENT_PUSH_PENDING;
|
||||
triangleBackground = SENT_PUSH_PENDING_TRIANGLE;
|
||||
} else if (messageRecord.isPending() || messageRecord.isFailed() || messageRecord.isPendingInsecureSmsFallback()) {
|
||||
background = SENT_SMS_PENDING;
|
||||
triangleBackground = SENT_SMS_PENDING_TRIANGLE;
|
||||
} else if (messageRecord.isPush()) {
|
||||
background = SENT_PUSH;
|
||||
triangleBackground = SENT_PUSH_TRIANGLE;
|
||||
} else {
|
||||
background = SENT_SMS;
|
||||
triangleBackground = SENT_SMS_TRIANGLE;
|
||||
}
|
||||
|
||||
setViewBackgroundWithoutResettingPadding(conversationParent, backgroundDrawables.getResourceId(background, -1));
|
||||
setViewBackgroundWithoutResettingPadding(triangleTick, backgroundDrawables.getResourceId(triangleBackground, -1));
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bubbleContainer.setState(transportationState, mediaCaptionState);
|
||||
}
|
||||
|
||||
private void setSelectionBackgroundDrawables(MessageRecord messageRecord) {
|
||||
int[] attributes = new int[]{R.attr.conversation_list_item_background_selected,
|
||||
|
@ -259,12 +239,30 @@ public class ConversationItem extends LinearLayout {
|
|||
drawables.recycle();
|
||||
}
|
||||
|
||||
private boolean hasConversationBubble(MessageRecord messageRecord) {
|
||||
return !messageRecord.isGroupAction();
|
||||
}
|
||||
|
||||
private boolean isCaptionlessMms(MessageRecord messageRecord) {
|
||||
return TextUtils.isEmpty(messageRecord.getDisplayBody()) && messageRecord.isMms();
|
||||
}
|
||||
|
||||
private boolean hasMedia(MessageRecord messageRecord) {
|
||||
return messageRecord.isMms() && ((MediaMmsMessageRecord)messageRecord).getPartCount() > 0;
|
||||
}
|
||||
|
||||
private void setBodyText(MessageRecord messageRecord) {
|
||||
bodyText.setClickable(false);
|
||||
bodyText.setFocusable(false);
|
||||
bodyText.setText(Emoji.getInstance(context).emojify(messageRecord.getDisplayBody(),
|
||||
new Emoji.InvalidatingPageLoadedListener(bodyText)),
|
||||
TextView.BufferType.SPANNABLE);
|
||||
|
||||
if (isCaptionlessMms(messageRecord)) {
|
||||
bodyText.setVisibility(View.GONE);
|
||||
} else {
|
||||
bodyText.setText(Emoji.getInstance(context).emojify(messageRecord.getDisplayBody(),
|
||||
new Emoji.InvalidatingPageLoadedListener(bodyText)),
|
||||
TextView.BufferType.SPANNABLE);
|
||||
bodyText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (bodyText.isClickable() && bodyText.isFocusable()) {
|
||||
bodyText.setOnLongClickListener(new MultiSelectLongClickListener());
|
||||
|
@ -272,6 +270,14 @@ public class ConversationItem extends LinearLayout {
|
|||
}
|
||||
}
|
||||
|
||||
private void setMediaAttributes(MessageRecord messageRecord) {
|
||||
if (messageRecord.isMmsNotification()) {
|
||||
setNotificationMmsAttributes((NotificationMmsMessageRecord) messageRecord);
|
||||
} else if (messageRecord.isMms()) {
|
||||
resolveMedia((MediaMmsMessageRecord) messageRecord);
|
||||
}
|
||||
}
|
||||
|
||||
private void setContactPhoto(MessageRecord messageRecord) {
|
||||
if (! messageRecord.isOutgoing()) {
|
||||
setContactPhotoForRecipient(messageRecord.getIndividualRecipient());
|
||||
|
@ -287,7 +293,6 @@ public class ConversationItem extends LinearLayout {
|
|||
bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isKeyExchange() ? R.drawable.ic_menu_login : 0, 0);
|
||||
deliveryImage.setVisibility(!messageRecord.isKeyExchange() && messageRecord.isDelivered() ? View.VISIBLE : View.GONE);
|
||||
|
||||
mmsThumbnail.setVisibility(View.GONE);
|
||||
mmsDownloadButton.setVisibility(View.GONE);
|
||||
mmsDownloadingLabel.setVisibility(View.GONE);
|
||||
|
||||
|
@ -299,7 +304,6 @@ public class ConversationItem extends LinearLayout {
|
|||
|
||||
private void setSentStatusIcons() {
|
||||
final long timestamp;
|
||||
|
||||
if (messageRecord.isPush()) timestamp = messageRecord.getDateSent();
|
||||
else timestamp = messageRecord.getDateReceived();
|
||||
|
||||
|
@ -321,9 +325,9 @@ public class ConversationItem extends LinearLayout {
|
|||
private void setMinimumWidth() {
|
||||
if (indicatorText != null && indicatorText.getVisibility() == View.VISIBLE && indicatorText.getText() != null) {
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
conversationParent.setMinimumWidth(indicatorText.getText().length() * (int)(6.5 * density));
|
||||
bodyBubble.setMinimumWidth(indicatorText.getText().length() * (int) (6.5 * density));
|
||||
} else {
|
||||
conversationParent.setMinimumWidth(0);
|
||||
bodyBubble.setMinimumWidth(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,44 +371,11 @@ public class ConversationItem extends LinearLayout {
|
|||
}
|
||||
}
|
||||
|
||||
private void setMediaMmsAttributes(MediaMmsMessageRecord messageRecord) {
|
||||
if (messageRecord.getPartCount() > 0) {
|
||||
mmsThumbnail.setVisibility(View.VISIBLE);
|
||||
mmsContainer.setVisibility(View.VISIBLE);
|
||||
mmsThumbnail.setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
} else {
|
||||
mmsThumbnail.setVisibility(View.GONE);
|
||||
mmsContainer.setVisibility(View.GONE);
|
||||
private void resolveMedia(MediaMmsMessageRecord messageRecord) {
|
||||
if (hasMedia(messageRecord)) {
|
||||
slideDeckFuture = messageRecord.getSlideDeckFuture();
|
||||
slideDeckFuture.addListener(slideDeckListener);
|
||||
}
|
||||
|
||||
slideDeck = messageRecord.getSlideDeckFuture();
|
||||
slideDeckListener = new FutureTaskListener<SlideDeck>() {
|
||||
@Override
|
||||
public void onSuccess(final SlideDeck result) {
|
||||
if (result == null)
|
||||
return;
|
||||
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Slide slide : result.getSlides()) {
|
||||
if (slide.hasImage()) {
|
||||
slide.setThumbnailOn(context, mmsThumbnail);
|
||||
mmsThumbnail.setOnClickListener(new ThumbnailClickListener(slide));
|
||||
mmsThumbnail.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mmsThumbnail.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable error) {}
|
||||
};
|
||||
slideDeck.addListener(slideDeckListener);
|
||||
}
|
||||
|
||||
/// Helper Methods
|
||||
|
@ -486,11 +457,16 @@ public class ConversationItem extends LinearLayout {
|
|||
intent.putExtra(MediaPreviewActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||
if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, messageRecord.getIndividualRecipient().getRecipientId());
|
||||
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getDateReceived());
|
||||
context.startActivity(intent);
|
||||
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
|
||||
context.startActivity(intent, mediaThumbnail.getThumbnailTransition().toBundle());
|
||||
} else {
|
||||
context.startActivity(intent);
|
||||
}
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.ConversationItem_view_secure_media_question);
|
||||
builder.setIcon(Dialogs.resolveIcon(context, R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(context, R.attr.dialog_alert_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(R.string.ConversationItem_this_media_has_been_stored_in_an_encrypted_database_external_viewer_warning);
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
|
@ -528,16 +504,6 @@ public class ConversationItem extends LinearLayout {
|
|||
}
|
||||
}
|
||||
|
||||
private class FailedIconClickListener implements View.OnClickListener {
|
||||
public void onClick(View v) {
|
||||
if (failedIconHandler != null && !messageRecord.isKeyExchange()) {
|
||||
Message message = Message.obtain();
|
||||
message.obj = messageRecord.getBody().getBody();
|
||||
failedIconHandler.dispatchMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClickListener implements View.OnClickListener {
|
||||
public void onClick(View v) {
|
||||
if (messageRecord.isFailed()) {
|
||||
|
@ -624,4 +590,58 @@ public class ConversationItem extends LinearLayout {
|
|||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private class ThumbnailListener implements FutureTaskListener<Pair<Drawable, Boolean>> {
|
||||
private final Object tag;
|
||||
|
||||
public ThumbnailListener(Object tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final Pair<Drawable, Boolean> result) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mediaThumbnail.getTag() == tag) {
|
||||
Log.w(TAG, "displaying media thumbnail");
|
||||
mediaThumbnail.show(result.first, result.second);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable error) {
|
||||
Log.w(TAG, error);
|
||||
mediaThumbnail.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private class SlideDeckListener implements FutureTaskListener<SlideDeck> {
|
||||
@Override
|
||||
public void onSuccess(final SlideDeck slideDeck) {
|
||||
if (slideDeck == null) return;
|
||||
|
||||
Slide slide = slideDeck.getThumbnailSlide(context);
|
||||
if (slide != null) {
|
||||
thumbnailFuture = slide.getThumbnail(context);
|
||||
if (thumbnailFuture != null) {
|
||||
Object tag = new Object();
|
||||
mediaThumbnail.setTag(tag);
|
||||
thumbnailListener = new ThumbnailListener(tag);
|
||||
thumbnailFuture.addListener(thumbnailListener);
|
||||
mediaThumbnail.setOnClickListener(new ThumbnailClickListener(slide));
|
||||
return;
|
||||
}
|
||||
}
|
||||
mediaThumbnail.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable error) {
|
||||
Log.w(TAG, error);
|
||||
mediaThumbnail.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -197,7 +197,7 @@ public class ConversationListFragment extends ListFragment
|
|||
|
||||
private void handleDeleteAllSelected() {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
||||
alert.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_alert_icon));
|
||||
alert.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_alert_icon));
|
||||
alert.setTitle(R.string.ConversationListFragment_delete_threads_question);
|
||||
alert.setMessage(R.string.ConversationListFragment_are_you_sure_you_wish_to_delete_all_selected_conversation_threads);
|
||||
alert.setCancelable(true);
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|||
import org.thoughtcrime.securesms.database.NoExternalStorageException;
|
||||
import org.thoughtcrime.securesms.database.PlaintextBackupExporter;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -59,7 +60,7 @@ public class ExportFragment extends Fragment {
|
|||
|
||||
// private void handleExportEncryptedBackup() {
|
||||
// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
// builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_info_icon));
|
||||
// builder.setIcon(Dialogs.getDrawable(getActivity(), R.attr.dialog_info_icon));
|
||||
// builder.setTitle(getActivity().getString(R.string.ExportFragment_export_to_sd_card));
|
||||
// builder.setMessage(getActivity().getString(R.string.ExportFragment_this_will_export_your_encrypted_keys_settings_and_messages));
|
||||
// builder.setPositiveButton(getActivity().getString(R.string.ExportFragment_export), new Dialog.OnClickListener() {
|
||||
|
@ -74,7 +75,7 @@ public class ExportFragment extends Fragment {
|
|||
|
||||
private void handleExportPlaintextBackup() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setTitle(getActivity().getString(R.string.ExportFragment_export_plaintext_to_sd_card));
|
||||
builder.setMessage(getActivity().getString(R.string.ExportFragment_warning_this_will_export_the_plaintext_contents));
|
||||
builder.setPositiveButton(getActivity().getString(R.string.ExportFragment_export), new Dialog.OnClickListener() {
|
||||
|
|
|
@ -19,24 +19,25 @@ package org.thoughtcrime.securesms;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.ImageMediaAdapter.ViewHolder;
|
||||
import org.thoughtcrime.securesms.components.ForegroundImageView;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.database.PartDatabase.ImageRecord;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
|
||||
import ws.com.google.android.mms.pdu.PduPart;
|
||||
|
@ -48,11 +49,11 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
|
|||
private final int gridSize;
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public ImageView imageView;
|
||||
public ForegroundImageView imageView;
|
||||
|
||||
public ViewHolder(View v) {
|
||||
super(v);
|
||||
imageView = (ImageView) v.findViewById(R.id.image);
|
||||
imageView = (ForegroundImageView) v.findViewById(R.id.image);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,8 +71,8 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder viewHolder, final Cursor cursor) {
|
||||
final ImageView imageView = viewHolder.imageView;
|
||||
final ImageRecord imageRecord = ImageRecord.from(cursor);
|
||||
final ForegroundImageView imageView = viewHolder.imageView;
|
||||
final ImageRecord imageRecord = ImageRecord.from(cursor);
|
||||
|
||||
PduPart part = new PduPart();
|
||||
|
||||
|
@ -79,8 +80,26 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
|
|||
part.setContentType(imageRecord.getContentType().getBytes());
|
||||
part.setId(imageRecord.getPartId());
|
||||
|
||||
imageView.setVisibility(View.INVISIBLE);
|
||||
Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType());
|
||||
if (slide != null) slide.setThumbnailOn(getContext(), imageView, gridSize, gridSize, new ColorDrawable(0x11ffffff));
|
||||
if (slide != null) {
|
||||
slide.getThumbnail(getContext()).addListener(new FutureTaskListener<Pair<Drawable, Boolean>>() {
|
||||
@Override
|
||||
public void onSuccess(final Pair<Drawable, Boolean> result) {
|
||||
imageView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
imageView.show(result.first, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable error) {
|
||||
Log.w(TAG, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
imageView.setOnClickListener(new OnMediaClickListener(imageRecord));
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.database.PlaintextBackupImporter;
|
|||
import org.thoughtcrime.securesms.service.ApplicationMigrationService;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -82,7 +83,7 @@ public class ImportFragment extends Fragment {
|
|||
|
||||
private void handleImportSms() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_info_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_info_icon));
|
||||
builder.setTitle(getActivity().getString(R.string.ImportFragment_import_system_sms_database));
|
||||
builder.setMessage(getActivity().getString(R.string.ImportFragment_this_will_import_messages_from_the_system));
|
||||
builder.setPositiveButton(getActivity().getString(R.string.ImportFragment_import), new AlertDialog.OnClickListener() {
|
||||
|
@ -108,7 +109,7 @@ public class ImportFragment extends Fragment {
|
|||
|
||||
private void handleImportEncryptedBackup() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setTitle(getActivity().getString(R.string.ImportFragment_restore_encrypted_backup));
|
||||
builder.setMessage(getActivity().getString(R.string.ImportFragment_restoring_an_encrypted_backup_will_completely_replace_your_existing_keys));
|
||||
builder.setPositiveButton(getActivity().getString(R.string.ImportFragment_restore), new AlertDialog.OnClickListener() {
|
||||
|
@ -123,7 +124,7 @@ public class ImportFragment extends Fragment {
|
|||
|
||||
private void handleImportPlaintextBackup() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setTitle(getActivity().getString(R.string.ImportFragment_import_plaintext_backup));
|
||||
builder.setMessage(getActivity().getString(R.string.ImportFragment_this_will_import_messages_from_a_plaintext_backup));
|
||||
builder.setPositiveButton(getActivity().getString(R.string.ImportFragment_import), new AlertDialog.OnClickListener() {
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.annotation.TargetApi;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.opengl.GLES20;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -31,12 +32,14 @@ import android.view.Menu;
|
|||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
|
@ -66,7 +69,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||
private MasterSecret masterSecret;
|
||||
private boolean paused;
|
||||
|
||||
private View loadingView;
|
||||
private TextView errorText;
|
||||
private Bitmap bitmap;
|
||||
private ImageView image;
|
||||
|
@ -82,6 +84,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||
dynamicLanguage.onCreate(this);
|
||||
|
||||
super.onCreate(bundle);
|
||||
|
||||
setFullscreenIfPossible();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
@ -146,7 +149,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||
}
|
||||
|
||||
private void initializeViews() {
|
||||
loadingView = findViewById(R.id.loading_indicator);
|
||||
errorText = (TextView) findViewById(R.id.error);
|
||||
image = (ImageView) findViewById(R.id.image);
|
||||
imageAttacher = new PhotoViewAttacher(image);
|
||||
|
@ -191,6 +193,13 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||
}
|
||||
|
||||
private void displayImage() {
|
||||
try {
|
||||
image.setImageBitmap(BitmapFactory.decodeStream(PartAuthority.getThumbnail(this, masterSecret, mediaUri)));
|
||||
image.setVisibility(View.VISIBLE);
|
||||
} catch (IOException fnfe) {
|
||||
Log.w(TAG, "tried to render thumbnail, but it wasn't found. carrying on.");
|
||||
}
|
||||
|
||||
new AsyncTask<Void,Void,Bitmap>() {
|
||||
@Override
|
||||
protected Bitmap doInBackground(Void... params) {
|
||||
|
@ -206,11 +215,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
loadingView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Bitmap bitmap) {
|
||||
if (paused) {
|
||||
|
@ -218,7 +222,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||
return;
|
||||
}
|
||||
|
||||
loadingView.setVisibility(View.GONE);
|
||||
if (bitmap == null) {
|
||||
errorText.setText(R.string.MediaPreviewActivity_cant_display);
|
||||
errorText.setVisibility(View.VISIBLE);
|
||||
|
|
168
src/org/thoughtcrime/securesms/components/BubbleContainer.java
Normal file
168
src/org/thoughtcrime/securesms/components/BubbleContainer.java
Normal file
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* 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.DrawableRes;
|
||||
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 ForegroundImageView 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 = (ForegroundImageView) 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) {
|
||||
media.reset();
|
||||
if (!isMediaPresent(mediaState)) {
|
||||
media.hide();
|
||||
}
|
||||
}
|
||||
|
||||
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_CAPTIONED) {
|
||||
parentParams.addRule(RelativeLayout.BELOW, 0);
|
||||
parentParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.image_view);
|
||||
} else {
|
||||
parentParams.addRule(RelativeLayout.BELOW, R.id.image_view);
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public class BubbleDrawableBuilder {
|
||||
private int color;
|
||||
private int shadowColor;
|
||||
private boolean hasShadow = true;
|
||||
private boolean[] corners = new boolean[]{true,true,true,true};
|
||||
|
||||
protected BubbleDrawableBuilder() { }
|
||||
|
||||
public BubbleDrawableBuilder setColor(int color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BubbleDrawableBuilder setShadowColor(int shadowColor) {
|
||||
this.shadowColor = shadowColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BubbleDrawableBuilder setHasShadow(boolean hasShadow) {
|
||||
this.hasShadow = hasShadow;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BubbleDrawableBuilder setCorners(boolean[] corners) {
|
||||
this.corners = corners;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Drawable create(Context context) {
|
||||
final GradientDrawable bubble = new GradientDrawable();
|
||||
final int radius = context.getResources().getDimensionPixelSize(R.dimen.message_bubble_corner_radius);
|
||||
final float[] radii = cornerBooleansToRadii(corners, radius);
|
||||
|
||||
bubble.setColor(color);
|
||||
bubble.setCornerRadii(radii);
|
||||
|
||||
if (!hasShadow) {
|
||||
return bubble;
|
||||
} else {
|
||||
final GradientDrawable shadow = new GradientDrawable();
|
||||
final int distance = context.getResources().getDimensionPixelSize(R.dimen.message_bubble_shadow_distance);
|
||||
|
||||
shadow.setColor(shadowColor);
|
||||
shadow.setCornerRadii(radii);
|
||||
|
||||
final LayerDrawable layers = new LayerDrawable(new Drawable[]{shadow, bubble});
|
||||
layers.setLayerInset(1, 0, 0, 0, distance);
|
||||
return layers;
|
||||
}
|
||||
}
|
||||
|
||||
private float[] cornerBooleansToRadii(boolean[] corners, int radius) {
|
||||
if (corners == null || corners.length != 4) {
|
||||
throw new AssertionError("there are four corners in a rectangle, silly");
|
||||
}
|
||||
|
||||
float[] radii = new float[8];
|
||||
int i = 0;
|
||||
for (boolean corner : corners) {
|
||||
radii[i] = radii[i+1] = corner ? radius : 0;
|
||||
i += 2;
|
||||
}
|
||||
|
||||
return radii;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,21 +16,28 @@
|
|||
|
||||
package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.widget.ImageView;
|
||||
import android.view.View;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
|
||||
import com.makeramen.RoundedImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
/**
|
||||
* https://gist.github.com/chrisbanes/9091754
|
||||
*/
|
||||
public class ForegroundImageView extends ImageView {
|
||||
public class ForegroundImageView extends RoundedImageView {
|
||||
|
||||
private Drawable mForeground;
|
||||
|
||||
|
@ -111,12 +118,66 @@ public class ForegroundImageView extends ImageView {
|
|||
}
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.JELLY_BEAN)
|
||||
public ActivityOptions getThumbnailTransition() {
|
||||
return ActivityOptions.makeScaleUpAnimation(this, 0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
public void show(Drawable drawable, boolean instantaneous) {
|
||||
setImageDrawable(drawable);
|
||||
if (drawable.getIntrinsicHeight() < (getHeight() * 0.75f) &&
|
||||
drawable.getIntrinsicWidth() < (getHeight() * 0.75f))
|
||||
{
|
||||
setScaleType(ScaleType.CENTER_INSIDE);
|
||||
} else {
|
||||
setScaleType(ScaleType.CENTER_CROP);
|
||||
}
|
||||
fadeIn(instantaneous ? 0 : 200);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
cancelAnimations();
|
||||
setImageDrawable(null);
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void fadeIn(final long millis) {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) fadeInModern(millis);
|
||||
else fadeInLegacy(millis);
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void fadeInLegacy(final long millis) {
|
||||
final AlphaAnimation alpha = new AlphaAnimation(0f, 1f);
|
||||
alpha.setDuration(millis);
|
||||
alpha.setFillAfter(true);
|
||||
startAnimation(alpha);
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.JELLY_BEAN)
|
||||
private void fadeInModern(final long millis) {
|
||||
setAlpha(0f);
|
||||
animate().alpha(1f).setDuration(millis);
|
||||
}
|
||||
|
||||
private void cancelAnimations() {
|
||||
if (getAnimation() != null) {
|
||||
getAnimation().cancel();
|
||||
clearAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable who) {
|
||||
return super.verifyDrawable(who) || (who == mForeground);
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(VERSION_CODES.HONEYCOMB)
|
||||
public void jumpDrawablesToCurrentState() {
|
||||
super.jumpDrawablesToCurrentState();
|
||||
if (mForeground != null) mForeground.jumpToCurrentState();
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -26,14 +26,15 @@ import android.os.AsyncTask;
|
|||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.provider.ContactsContract;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -79,20 +80,25 @@ public class AttachmentManager {
|
|||
public void setMedia(final Slide slide, final int thumbnailWidth, final int thumbnailHeight) {
|
||||
slideDeck.clear();
|
||||
slideDeck.addSlide(slide);
|
||||
new AsyncTask<Void,Void,Drawable>() {
|
||||
|
||||
slide.getThumbnail(context).addListener(new FutureTaskListener<Pair<Drawable, Boolean>>() {
|
||||
@Override
|
||||
protected Drawable doInBackground(Void... params) {
|
||||
return slide.getThumbnail(context, thumbnailWidth, thumbnailHeight);
|
||||
public void onSuccess(final Pair<Drawable, Boolean> result) {
|
||||
thumbnail.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
thumbnail.setImageDrawable(result.first);
|
||||
attachmentView.setVisibility(View.VISIBLE);
|
||||
attachmentListener.onAttachmentChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Drawable drawable) {
|
||||
thumbnail.setImageDrawable(drawable);
|
||||
attachmentView.setVisibility(View.VISIBLE);
|
||||
attachmentListener.onAttachmentChanged();
|
||||
public void onFailure(Throwable error) {
|
||||
Log.w(TAG, error);
|
||||
slideDeck.clear();
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
}
|
||||
|
||||
public void setMedia(Slide slide) {
|
||||
|
|
|
@ -20,20 +20,20 @@ import java.io.IOException;
|
|||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.SmilUtil;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.w3c.dom.smil.SMILDocument;
|
||||
import org.w3c.dom.smil.SMILMediaElement;
|
||||
import org.w3c.dom.smil.SMILRegionElement;
|
||||
import org.w3c.dom.smil.SMILRegionMediaElement;
|
||||
|
||||
import ws.com.google.android.mms.pdu.PduPart;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore.Audio;
|
||||
import android.util.Pair;
|
||||
|
||||
public class AudioSlide extends Slide {
|
||||
|
||||
|
@ -66,8 +66,8 @@ public class AudioSlide extends Slide {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Drawable getThumbnail(Context context, int maxWidth, int maxHeight) {
|
||||
return ThemeUtil.resolveIcon(context, R.attr.conversation_icon_attach_audio);
|
||||
public ListenableFutureTask<Pair<Drawable,Boolean>> getThumbnail(Context context) {
|
||||
return new ListenableFutureTask<>(new Pair<>(ResUtil.getDrawable(context, R.attr.conversation_icon_attach_audio), true));
|
||||
}
|
||||
|
||||
public static PduPart constructPartFromUri(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
||||
|
|
|
@ -18,38 +18,32 @@ package org.thoughtcrime.securesms.mms;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil.ThumbnailData;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.SmilUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.w3c.dom.smil.SMILDocument;
|
||||
import org.w3c.dom.smil.SMILMediaElement;
|
||||
import org.w3c.dom.smil.SMILRegionElement;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import ws.com.google.android.mms.ContentType;
|
||||
import ws.com.google.android.mms.pdu.PduPart;
|
||||
|
@ -70,106 +64,50 @@ public class ImageSlide extends Slide {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Drawable getThumbnail(Context context, int maxWidth, int maxHeight) {
|
||||
public ListenableFutureTask<Pair<Drawable,Boolean>> getThumbnail(Context context) {
|
||||
if (getPart().isPendingPush()) {
|
||||
return new ListenableFutureTask<>(new Pair<>(context.getResources().getDrawable(R.drawable.stat_sys_download), true));
|
||||
}
|
||||
|
||||
Drawable thumbnail = getCachedThumbnail();
|
||||
|
||||
if (thumbnail != null) {
|
||||
return thumbnail;
|
||||
Log.w(TAG, "getThumbnail() returning cached thumbnail");
|
||||
return new ListenableFutureTask<>(new Pair<>(thumbnail, true));
|
||||
}
|
||||
|
||||
if (part.isPendingPush()) {
|
||||
return context.getResources().getDrawable(R.drawable.stat_sys_download);
|
||||
}
|
||||
|
||||
try {
|
||||
Bitmap thumbnailBitmap;
|
||||
long startDecode = System.currentTimeMillis();
|
||||
|
||||
if (part.getDataUri() != null && part.getId() > -1) {
|
||||
thumbnailBitmap = BitmapFactory.decodeStream(DatabaseFactory.getPartDatabase(context)
|
||||
.getThumbnailStream(masterSecret, part.getId()));
|
||||
} else if (part.getDataUri() != null) {
|
||||
Log.w(TAG, "generating thumbnail for new part");
|
||||
ThumbnailData thumbnailData = MediaUtil.generateThumbnail(context, masterSecret,
|
||||
part.getDataUri(), Util.toIsoString(part.getContentType()));
|
||||
thumbnailBitmap = thumbnailData.getBitmap();
|
||||
part.setThumbnail(thumbnailBitmap);
|
||||
} else {
|
||||
throw new FileNotFoundException("no data location specified");
|
||||
}
|
||||
|
||||
Log.w(TAG, "thumbnail decode/generate time: " + (System.currentTimeMillis() - startDecode) + "ms");
|
||||
|
||||
thumbnail = new BitmapDrawable(context.getResources(), thumbnailBitmap);
|
||||
thumbnailCache.put(part.getDataUri(), new SoftReference<>(thumbnail));
|
||||
|
||||
return thumbnail;
|
||||
} catch (IOException | BitmapDecodingException e) {
|
||||
Log.w(TAG, e);
|
||||
return context.getResources().getDrawable(R.drawable.ic_missing_thumbnail_picture);
|
||||
}
|
||||
Log.w(TAG, "getThumbnail() resolving thumbnail, as it wasn't cached");
|
||||
return resolveThumbnail(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThumbnailOn(Context context, ImageView imageView) {
|
||||
setThumbnailOn(context, imageView, imageView.getWidth(), imageView.getHeight(), new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
private ListenableFutureTask<Pair<Drawable,Boolean>> resolveThumbnail(Context context) {
|
||||
final WeakReference<Context> weakContext = new WeakReference<>(context);
|
||||
|
||||
@Override
|
||||
public void setThumbnailOn(Context context, ImageView imageView, final int width, final int height, final Drawable placeholder) {
|
||||
Drawable thumbnail = getCachedThumbnail();
|
||||
|
||||
if (thumbnail != null) {
|
||||
Log.w("ImageSlide", "Setting cached thumbnail...");
|
||||
setThumbnailOn(imageView, thumbnail, true);
|
||||
return;
|
||||
}
|
||||
|
||||
final WeakReference<Context> weakContext = new WeakReference<>(context);
|
||||
final WeakReference<ImageView> weakImageView = new WeakReference<>(imageView);
|
||||
final Handler handler = new Handler();
|
||||
|
||||
imageView.setImageDrawable(placeholder);
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
|
||||
MmsDatabase.slideResolver.execute(new Runnable() {
|
||||
Callable<Pair<Drawable,Boolean>> slideCallable = new Callable<Pair<Drawable, Boolean>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
public Pair<Drawable, Boolean> call() throws Exception {
|
||||
final Context context = weakContext.get();
|
||||
if (context == null) {
|
||||
Log.w(TAG, "context SoftReference was null, leaving");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
final Drawable bitmap = getThumbnail(context, width, height);
|
||||
final ImageView destination = weakImageView.get();
|
||||
try {
|
||||
final long startDecode = System.currentTimeMillis();
|
||||
final Bitmap thumbnailBitmap = MediaUtil.getOrGenerateThumbnail(context, masterSecret, part);
|
||||
final Drawable thumbnail = new BitmapDrawable(context.getResources(), thumbnailBitmap);
|
||||
Log.w(TAG, "thumbnail decode/generate time: " + (System.currentTimeMillis() - startDecode) + "ms");
|
||||
|
||||
Log.w(TAG, "slide resolved, destination available? " + (destination == null));
|
||||
if (destination != null && destination.getDrawable() == placeholder) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setThumbnailOn(destination, bitmap, false);
|
||||
}
|
||||
});
|
||||
thumbnailCache.put(part.getDataUri(), new SoftReference<>(thumbnail));
|
||||
return new Pair<>(thumbnail, false);
|
||||
} catch (IOException | BitmapDecodingException e) {
|
||||
Log.w(TAG, e);
|
||||
return new Pair<>(context.getResources().getDrawable(R.drawable.ic_missing_thumbnail_picture), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setThumbnailOn(ImageView imageView, Drawable thumbnail, boolean fromMemory) {
|
||||
if (fromMemory) {
|
||||
imageView.setImageDrawable(thumbnail);
|
||||
} else if (thumbnail instanceof AnimationDrawable) {
|
||||
imageView.setImageDrawable(thumbnail);
|
||||
((AnimationDrawable)imageView.getDrawable()).start();
|
||||
} else {
|
||||
TransitionDrawable fadingResult = new TransitionDrawable(new Drawable[]{imageView.getDrawable(), thumbnail});
|
||||
imageView.setImageDrawable(fadingResult);
|
||||
fadingResult.startTransition(300);
|
||||
}
|
||||
};
|
||||
ListenableFutureTask<Pair<Drawable,Boolean>> futureTask = new ListenableFutureTask<>(slideCallable);
|
||||
MmsDatabase.slideResolver.execute(futureTask);
|
||||
return futureTask;
|
||||
}
|
||||
|
||||
private Drawable getCachedThumbnail() {
|
||||
|
|
|
@ -43,6 +43,18 @@ public class PartAuthority {
|
|||
}
|
||||
}
|
||||
|
||||
public static InputStream getThumbnail(Context context, MasterSecret masterSecret, Uri uri)
|
||||
throws IOException
|
||||
{
|
||||
PartDatabase partDatabase = DatabaseFactory.getPartDatabase(context);
|
||||
int match = uriMatcher.match(uri);
|
||||
|
||||
switch (match) {
|
||||
case PART_ROW: return partDatabase.getThumbnailStream(masterSecret, ContentUris.parseId(uri));
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Uri getPublicPartUri(Uri uri) {
|
||||
return ContentUris.withAppendedId(PartProvider.CONTENT_URI, ContentUris.parseId(uri));
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.mms;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.w3c.dom.smil.SMILDocument;
|
||||
import org.w3c.dom.smil.SMILMediaElement;
|
||||
|
@ -30,8 +31,7 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.ImageView;
|
||||
import android.util.Pair;
|
||||
|
||||
import ws.com.google.android.mms.pdu.PduPart;
|
||||
|
||||
|
@ -71,20 +71,10 @@ public abstract class Slide {
|
|||
return part.getDataUri();
|
||||
}
|
||||
|
||||
public Drawable getThumbnail(Context context, int maxWidth, int maxHeight) {
|
||||
public ListenableFutureTask<Pair<Drawable,Boolean>> getThumbnail(Context context) {
|
||||
throw new AssertionError("getThumbnail() called on non-thumbnail producing slide!");
|
||||
}
|
||||
|
||||
public void setThumbnailOn(Context context, ImageView imageView) {
|
||||
imageView.setImageDrawable(getThumbnail(context, imageView.getWidth(), imageView.getHeight()));
|
||||
}
|
||||
|
||||
public void setThumbnailOn(Context context, ImageView imageView, int height, int width, Drawable placeholder) {
|
||||
imageView.setImageDrawable(getThumbnail(context, width, height));
|
||||
}
|
||||
|
||||
public Bitmap getGeneratedThumbnail() { return null; }
|
||||
|
||||
public boolean hasImage() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.dom.smil.parser.SmilXmlSerializer;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.SmilUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
@ -90,8 +94,15 @@ public class SlideDeck {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Slide getThumbnailSlide(Context context) {
|
||||
for (Slide slide : slides) {
|
||||
if (slide.hasImage()) {
|
||||
return slide;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,9 @@ import java.io.IOException;
|
|||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.SmilUtil;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.w3c.dom.smil.SMILDocument;
|
||||
import org.w3c.dom.smil.SMILMediaElement;
|
||||
import org.w3c.dom.smil.SMILRegionElement;
|
||||
|
@ -29,12 +30,12 @@ import org.w3c.dom.smil.SMILRegionElement;
|
|||
import ws.com.google.android.mms.pdu.PduPart;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
public class VideoSlide extends Slide {
|
||||
|
||||
|
@ -47,8 +48,8 @@ public class VideoSlide extends Slide {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Drawable getThumbnail(Context context, int width, int height) {
|
||||
return ThemeUtil.resolveIcon(context, R.attr.conversation_icon_attach_video);
|
||||
public ListenableFutureTask<Pair<Drawable,Boolean>> getThumbnail(Context context) {
|
||||
return new ListenableFutureTask<>(new Pair<>(ResUtil.getDrawable(context, R.attr.conversation_icon_attach_video), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -123,7 +124,7 @@ public class AppProtectionPreferenceFragment extends PreferenceFragment {
|
|||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setTitle(R.string.ApplicationPreferencesActivity_disable_storage_encryption);
|
||||
builder.setMessage(R.string.ApplicationPreferencesActivity_warning_this_will_disable_storage_encryption_for_all_messages);
|
||||
builder.setIcon(Dialogs.resolveIcon(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(getActivity(), R.attr.dialog_alert_icon));
|
||||
builder.setPositiveButton(R.string.ApplicationPreferencesActivity_disable, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import android.widget.Toast;
|
|||
|
||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
|
||||
|
@ -82,7 +83,7 @@ public class LedBlinkPatternListPreference extends ListPreference implements OnS
|
|||
|
||||
private void initializeDialog(View view) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setIcon(Dialogs.resolveIcon(context, R.attr.dialog_info_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(context, R.attr.dialog_info_icon));
|
||||
builder.setTitle(R.string.preferences__pref_led_blink_custom_pattern_title);
|
||||
builder.setView(view);
|
||||
builder.setOnCancelListener(new CustomDialogCancelListener());
|
||||
|
|
|
@ -28,22 +28,17 @@ public class Dialogs {
|
|||
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||
dialog.setTitle(title);
|
||||
dialog.setMessage(message);
|
||||
dialog.setIcon(resolveIcon(context, R.attr.dialog_alert_icon));
|
||||
dialog.setPositiveButton(android.R.string.ok, null);
|
||||
dialog.show();
|
||||
}
|
||||
public static void showInfoDialog(Context context, String title, String message) {
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||
dialog.setTitle(title);
|
||||
dialog.setMessage(message);
|
||||
dialog.setIcon(resolveIcon(context, R.attr.dialog_info_icon));
|
||||
dialog.setIcon(ResUtil.getDrawable(context, R.attr.dialog_alert_icon));
|
||||
dialog.setPositiveButton(android.R.string.ok, null);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static Drawable resolveIcon(Context c, int iconAttr) {
|
||||
TypedValue out = new TypedValue();
|
||||
c.getTheme().resolveAttribute(iconAttr, out, true);
|
||||
return c.getResources().getDrawable(out.resourceId);
|
||||
public static void showInfoDialog(Context context, String title, String message) {
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||
dialog.setTitle(title);
|
||||
dialog.setMessage(message);
|
||||
dialog.setIcon(ResUtil.getDrawable(context, R.attr.dialog_info_icon));
|
||||
dialog.setPositiveButton(android.R.string.ok, null);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,16 @@ public class ListenableFutureTask<V> extends FutureTask<V> {
|
|||
super(callable);
|
||||
}
|
||||
|
||||
public ListenableFutureTask(final V result) {
|
||||
super(new Callable<V>() {
|
||||
@Override
|
||||
public V call() throws Exception {
|
||||
return result;
|
||||
}
|
||||
});
|
||||
this.run();
|
||||
}
|
||||
|
||||
public synchronized void addListener(FutureTaskListener<V> listener) {
|
||||
if (this.isDone()) {
|
||||
callback(listener);
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.util;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
|
@ -50,6 +51,22 @@ public class MediaUtil {
|
|||
return data;
|
||||
}
|
||||
|
||||
public static Bitmap getOrGenerateThumbnail(Context context, MasterSecret masterSecret, PduPart part)
|
||||
throws IOException, BitmapDecodingException
|
||||
{
|
||||
if (part.getDataUri() != null && part.getId() > -1) {
|
||||
return BitmapFactory.decodeStream(DatabaseFactory.getPartDatabase(context)
|
||||
.getThumbnailStream(masterSecret, part.getId()));
|
||||
} else if (part.getDataUri() != null) {
|
||||
Log.w(TAG, "generating thumbnail for new part");
|
||||
Bitmap bitmap = MediaUtil.generateThumbnail(context, masterSecret, part.getDataUri(), Util.toIsoString(part.getContentType())).getBitmap();
|
||||
part.setThumbnail(bitmap);
|
||||
return bitmap;
|
||||
} else {
|
||||
throw new FileNotFoundException("no data location specified");
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getPartData(Context context, MasterSecret masterSecret, PduPart part)
|
||||
throws IOException
|
||||
{
|
||||
|
|
|
@ -18,14 +18,27 @@
|
|||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.util.TypedValue;
|
||||
|
||||
public class ThemeUtil {
|
||||
public static Drawable resolveIcon(Context c, int iconAttr)
|
||||
{
|
||||
TypedValue out = new TypedValue();
|
||||
c.getTheme().resolveAttribute(iconAttr, out, true);
|
||||
return c.getResources().getDrawable(out.resourceId);
|
||||
public class ResUtil {
|
||||
|
||||
public static int getColor(Context context, @AttrRes int attr) {
|
||||
final TypedArray styledAttributes = context.obtainStyledAttributes(new int[]{attr});
|
||||
final int result = styledAttributes.getColor(0, -1);
|
||||
styledAttributes.recycle();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int getDrawableRes(Context c, @AttrRes int attr) {
|
||||
final TypedValue out = new TypedValue();
|
||||
c.getTheme().resolveAttribute(attr, out, true);
|
||||
return out.resourceId;
|
||||
}
|
||||
|
||||
public static Drawable getDrawable(Context c, @AttrRes int attr) {
|
||||
return c.getResources().getDrawable(getDrawableRes(c, attr));
|
||||
}
|
||||
}
|
|
@ -152,7 +152,7 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask<SaveAttachmentTa
|
|||
public static void showWarningDialog(Context context, OnClickListener onAcceptListener) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.ConversationFragment_save_to_sd_card);
|
||||
builder.setIcon(Dialogs.resolveIcon(context, R.attr.dialog_alert_icon));
|
||||
builder.setIcon(ResUtil.getDrawable(context, R.attr.dialog_alert_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(R.string.ConversationFragment_this_media_has_been_stored_in_an_encrypted_database_warning);
|
||||
builder.setPositiveButton(R.string.yes, onAcceptListener);
|
||||
|
|
41
src/org/thoughtcrime/securesms/util/ViewUtil.java
Normal file
41
src/org/thoughtcrime/securesms/util/ViewUtil.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* 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.util;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.view.View;
|
||||
|
||||
public class ViewUtil {
|
||||
public static void setBackgroundSavingPadding(View v, Drawable drawable) {
|
||||
final int paddingBottom = v.getPaddingBottom();
|
||||
final int paddingLeft = v.getPaddingLeft();
|
||||
final int paddingRight = v.getPaddingRight();
|
||||
final int paddingTop = v.getPaddingTop();
|
||||
v.setBackgroundDrawable(drawable);
|
||||
v.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
}
|
||||
|
||||
public static void setBackgroundSavingPadding(View v, @DrawableRes int resId) {
|
||||
final int paddingBottom = v.getPaddingBottom();
|
||||
final int paddingLeft = v.getPaddingLeft();
|
||||
final int paddingRight = v.getPaddingRight();
|
||||
final int paddingTop = v.getPaddingTop();
|
||||
v.setBackgroundResource(resId);
|
||||
v.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue