15
res/anim/animation_toggle_in.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<scale
|
||||||
|
android:duration="150"
|
||||||
|
android:fromXScale="0.6"
|
||||||
|
android:fromYScale="0.6"
|
||||||
|
android:toXScale="1.0"
|
||||||
|
android:toYScale="1.0"
|
||||||
|
android:pivotX="50%"
|
||||||
|
android:pivotY="50%" />
|
||||||
|
<alpha
|
||||||
|
android:duration="150"
|
||||||
|
android:fromAlpha="0.0"
|
||||||
|
android:toAlpha="1.0" />
|
||||||
|
</set>
|
15
res/anim/animation_toggle_out.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<scale
|
||||||
|
android:duration="150"
|
||||||
|
android:fromXScale="1.0"
|
||||||
|
android:fromYScale="1.0"
|
||||||
|
android:toXScale="0.60"
|
||||||
|
android:toYScale="0.60"
|
||||||
|
android:pivotX="50%"
|
||||||
|
android:pivotY="50%" />
|
||||||
|
<alpha
|
||||||
|
android:duration="150"
|
||||||
|
android:fromAlpha="1.0"
|
||||||
|
android:toAlpha="0.0" />
|
||||||
|
</set>
|
BIN
res/drawable-hdpi/ic_send_push_white_24dp.png
Normal file
After Width: | Height: | Size: 757 B |
BIN
res/drawable-hdpi/ic_send_sms_white_24dp.png
Normal file
After Width: | Height: | Size: 757 B |
BIN
res/drawable-mdpi/ic_send_push_white_24dp.png
Normal file
After Width: | Height: | Size: 485 B |
BIN
res/drawable-mdpi/ic_send_sms_white_24dp.png
Normal file
After Width: | Height: | Size: 485 B |
9
res/drawable-v21/circle_touch_highlight_background.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="@color/touch_highlight">
|
||||||
|
<item android:id="@android:id/mask">
|
||||||
|
<shape android:shape="oval">
|
||||||
|
<solid android:color="@color/black" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
BIN
res/drawable-xhdpi/ic_send_push_white_24dp.png
Normal file
After Width: | Height: | Size: 973 B |
BIN
res/drawable-xhdpi/ic_send_sms_white_24dp.png
Normal file
After Width: | Height: | Size: 956 B |
BIN
res/drawable-xxhdpi/ic_send_push_white_24dp.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
res/drawable-xxhdpi/ic_send_sms_white_24dp.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
res/drawable-xxhdpi/ic_send_white_24dp.png
Normal file
After Width: | Height: | Size: 562 B |
BIN
res/drawable-xxxhdpi/ic_send_push_white_24dp.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
res/drawable-xxxhdpi/ic_send_sms_white_24dp.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
5
res/drawable/circle_tintable.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="oval">
|
||||||
|
<solid android:color="@color/white" />
|
||||||
|
</shape>
|
8
res/drawable/circle_touch_highlight_background.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="oval">
|
||||||
|
<solid android:color="@color/touch_highlight" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
@ -1,9 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
<solid android:color="@android:color/transparent" />
|
<solid android:color="@null" />
|
||||||
<padding android:bottom="@dimen/conversation_activity_compose_padding"
|
|
||||||
android:left="@dimen/conversation_activity_compose_padding"
|
|
||||||
android:right="@dimen/conversation_activity_compose_padding"
|
|
||||||
android:top="@dimen/conversation_activity_compose_padding" />
|
|
||||||
</shape>
|
</shape>
|
@ -4,6 +4,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:background="?conversation_background"
|
android:background="?conversation_background"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
@ -60,73 +61,65 @@
|
|||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<View android:layout_width="match_parent"
|
<LinearLayout android:id="@+id/bottom_panel"
|
||||||
android:layout_height="1px"
|
android:layout_width="fill_parent"
|
||||||
android:background="?conversation_editor_background" />
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="5dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout android:id="@+id/compose_bubble"
|
||||||
android:id="@+id/bottom_panel"
|
android:layout_width="0dp"
|
||||||
android:layout_width="fill_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="1"
|
||||||
android:orientation="horizontal">
|
android:background="@drawable/sent_bubble">
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiToggle
|
<org.thoughtcrime.securesms.components.emoji.EmojiToggle
|
||||||
android:id="@+id/emoji_toggle"
|
android:id="@+id/emoji_toggle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="37dp"
|
||||||
android:layout_height="44dp"
|
android:layout_height="37dp"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:background="@drawable/touch_highlight_background"
|
android:background="@drawable/touch_highlight_background"
|
||||||
android:contentDescription="@string/conversation_activity__emoji_toggle_description"
|
android:contentDescription="@string/conversation_activity__emoji_toggle_description" />
|
||||||
android:padding="10dp"/>
|
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.ComposeText
|
<org.thoughtcrime.securesms.components.ComposeText
|
||||||
|
style="@style/ComposeEditText"
|
||||||
android:id="@+id/embedded_text_editor"
|
android:id="@+id/embedded_text_editor"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1.0"
|
android:minHeight="37dp"
|
||||||
android:autoText="true"
|
android:layout_gravity="center_vertical"
|
||||||
android:capitalize="sentences"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/compose_background"
|
|
||||||
android:paddingTop="12dp"
|
|
||||||
android:paddingBottom="12dp"
|
|
||||||
android:paddingRight="0dp"
|
|
||||||
android:paddingLeft="0dp"
|
|
||||||
android:imeOptions="actionSend|flagNoEnterAction|flagNoExtractUi"
|
|
||||||
android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
|
|
||||||
android:maxLength="2000"
|
|
||||||
android:maxLines="4"
|
|
||||||
android:nextFocusForward="@+id/send_button"
|
android:nextFocusForward="@+id/send_button"
|
||||||
android:nextFocusRight="@+id/send_button"
|
android:nextFocusRight="@+id/send_button"
|
||||||
android:contentDescription="@string/conversation_activity__compose_description"
|
tools:hint="Send TextSecure message" />
|
||||||
android:textColor="?conversation_editor_text_color" />
|
</LinearLayout>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.AnimatingToggle
|
<org.thoughtcrime.securesms.components.AnimatingToggle
|
||||||
android:id="@+id/button_toggle"
|
android:id="@+id/button_toggle"
|
||||||
android:layout_width="46dp"
|
android:layout_width="50dp"
|
||||||
android:layout_height="44dp"
|
android:layout_height="50dp"
|
||||||
android:layout_gravity="bottom">
|
android:background="@drawable/circle_tintable"
|
||||||
|
android:layout_gravity="bottom">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/attach_button"
|
android:id="@+id/attach_button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="@drawable/touch_highlight_background"
|
android:background="@drawable/circle_touch_highlight_background"
|
||||||
android:src="?conversation_attach"
|
android:src="@drawable/ic_attach_white_24dp"
|
||||||
android:contentDescription="@string/ConversationActivity_add_attachment"
|
android:contentDescription="@string/ConversationActivity_add_attachment"
|
||||||
android:nextFocusLeft="@+id/embedded_text_editor" />
|
android:nextFocusLeft="@+id/embedded_text_editor" />
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.SendButton
|
<org.thoughtcrime.securesms.components.SendButton
|
||||||
android:id="@+id/send_button"
|
android:id="@+id/send_button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/touch_highlight_background"
|
android:contentDescription="@string/conversation_activity__send"
|
||||||
android:contentDescription="@string/conversation_activity__send"
|
android:nextFocusLeft="@+id/embedded_text_editor"
|
||||||
android:nextFocusLeft="@+id/embedded_text_editor"
|
android:src="?conversation_transport_sms_indicator"
|
||||||
android:src="?conversation_transport_sms_indicator"
|
android:background="@drawable/circle_touch_highlight_background" />
|
||||||
android:focusable="true"
|
|
||||||
android:clickable="false"
|
|
||||||
android:enabled="false" />
|
|
||||||
|
|
||||||
</org.thoughtcrime.securesms.components.AnimatingToggle>
|
</org.thoughtcrime.securesms.components.AnimatingToggle>
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?conversation_transport_popup_background">
|
android:background="?conversation_transport_popup_background"
|
||||||
|
android:elevation="2dp">
|
||||||
<ListView android:id="@+id/transport_selection_list"
|
<ListView android:id="@+id/transport_selection_list"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="@dimen/transport_selection_popup_width"
|
android:layout_width="@dimen/transport_selection_popup_width"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
@ -10,11 +11,16 @@
|
|||||||
<ImageView android:id="@+id/icon"
|
<ImageView android:id="@+id/icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/transport_selection_list_item__transport_icon"/>
|
android:padding="7dp"
|
||||||
|
android:background="@drawable/circle_tintable"
|
||||||
|
android:contentDescription="@string/transport_selection_list_item__transport_icon"
|
||||||
|
tools:src="@drawable/ic_send_push_white_24dp"
|
||||||
|
tools:backgroundTint="@color/textsecure_primary" />
|
||||||
<TextView android:id="@+id/text"
|
<TextView android:id="@+id/text"
|
||||||
android:paddingLeft="10dp"
|
android:paddingLeft="10dp"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="TextSecure" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="touch_highlight">#10000000</color>
|
<color name="touch_highlight">#22000000</color>
|
||||||
</resources>
|
</resources>
|
@ -7,8 +7,8 @@
|
|||||||
<dimen name="emoji_drawer_left_right_padding">5dp</dimen>
|
<dimen name="emoji_drawer_left_right_padding">5dp</dimen>
|
||||||
<dimen name="conversation_item_date_text_size">12sp</dimen>
|
<dimen name="conversation_item_date_text_size">12sp</dimen>
|
||||||
<dimen name="transport_selection_popup_width">200sp</dimen>
|
<dimen name="transport_selection_popup_width">200sp</dimen>
|
||||||
<dimen name="transport_selection_popup_xoff">0dp</dimen>
|
<dimen name="transport_selection_popup_xoff">2dp</dimen>
|
||||||
<dimen name="transport_selection_popup_yoff">1dp</dimen>
|
<dimen name="transport_selection_popup_yoff">2dp</dimen>
|
||||||
<dimen name="contact_photo_target_size">64dp</dimen>
|
<dimen name="contact_photo_target_size">64dp</dimen>
|
||||||
<dimen name="contact_selection_photo_size">50dp</dimen>
|
<dimen name="contact_selection_photo_size">50dp</dimen>
|
||||||
<dimen name="thumbnail_max_size">230dp</dimen>
|
<dimen name="thumbnail_max_size">230dp</dimen>
|
||||||
|
@ -176,4 +176,18 @@
|
|||||||
<item name="android:background">@drawable/error_round</item>
|
<item name="android:background">@drawable/error_round</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="ComposeEditText" parent="@style/Widget.AppCompat.EditText">
|
||||||
|
<item name="android:padding">2dp</item>
|
||||||
|
<item name="android:background">@null</item>
|
||||||
|
<item name="android:maxLines">4</item>
|
||||||
|
<item name="android:maxLength">2000</item>
|
||||||
|
<item name="android:textColor">?conversation_item_sent_text_primary_color</item>
|
||||||
|
<item name="android:capitalize">sentences</item>
|
||||||
|
<item name="android:autoText">true</item>
|
||||||
|
<item name="android:gravity">center_vertical</item>
|
||||||
|
<item name="android:imeOptions">actionSend|flagNoEnterAction|flagNoExtractUi</item>
|
||||||
|
<item name="android:inputType">textAutoCorrect|textCapSentences|textMultiLine</item>
|
||||||
|
<item name="android:contentDescription">@string/conversation_activity__compose_description</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -23,6 +23,11 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuff.Mode;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
@ -30,6 +35,7 @@ import android.os.Build;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
@ -154,6 +160,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
private ConversationFragment fragment;
|
private ConversationFragment fragment;
|
||||||
private Button unblockButton;
|
private Button unblockButton;
|
||||||
private View composePanel;
|
private View composePanel;
|
||||||
|
private View composeBubble;
|
||||||
|
|
||||||
private AttachmentTypeSelectorAdapter attachmentAdapter;
|
private AttachmentTypeSelectorAdapter attachmentAdapter;
|
||||||
private AttachmentManager attachmentManager;
|
private AttachmentManager attachmentManager;
|
||||||
@ -732,6 +739,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
titleView = (ConversationTitleView) getSupportActionBar().getCustomView();
|
titleView = (ConversationTitleView) getSupportActionBar().getCustomView();
|
||||||
unblockButton = (Button) findViewById(R.id.unblock_button);
|
unblockButton = (Button) findViewById(R.id.unblock_button);
|
||||||
composePanel = findViewById(R.id.bottom_panel);
|
composePanel = findViewById(R.id.bottom_panel);
|
||||||
|
composeBubble = findViewById(R.id.compose_bubble);
|
||||||
|
|
||||||
|
int[] attributes = new int[]{R.attr.conversation_item_bubble_background};
|
||||||
|
TypedArray colors = obtainStyledAttributes(attributes);
|
||||||
|
int defaultColor = colors.getColor(0, Color.WHITE);
|
||||||
|
composeBubble.getBackground().setColorFilter(defaultColor, PorterDuff.Mode.MULTIPLY);
|
||||||
|
colors.recycle();
|
||||||
|
|
||||||
attachmentAdapter = new AttachmentTypeSelectorAdapter(this);
|
attachmentAdapter = new AttachmentTypeSelectorAdapter(this);
|
||||||
attachmentManager = new AttachmentManager(this, this);
|
attachmentManager = new AttachmentManager(this, this);
|
||||||
@ -747,6 +761,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
public void onChange(TransportOption newTransport) {
|
public void onChange(TransportOption newTransport) {
|
||||||
calculateCharactersRemaining();
|
calculateCharactersRemaining();
|
||||||
composeText.setHint(newTransport.getComposeHint());
|
composeText.setHint(newTransport.getComposeHint());
|
||||||
|
buttonToggle.getBackground().setColorFilter(newTransport.getBackgroundColor(), Mode.MULTIPLY);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
|
import android.support.annotation.DrawableRes;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.CharacterCalculator;
|
import org.thoughtcrime.securesms.util.CharacterCalculator;
|
||||||
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
|
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
|
||||||
|
|
||||||
@ -11,19 +13,22 @@ public class TransportOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int drawable;
|
private int drawable;
|
||||||
|
private int backgroundColor;
|
||||||
private String text;
|
private String text;
|
||||||
private Type type;
|
private Type type;
|
||||||
private String composeHint;
|
private String composeHint;
|
||||||
private CharacterCalculator characterCalculator;
|
private CharacterCalculator characterCalculator;
|
||||||
|
|
||||||
public TransportOption(Type type,
|
public TransportOption(Type type,
|
||||||
int drawable,
|
@DrawableRes int drawable,
|
||||||
|
int backgroundColor,
|
||||||
String text,
|
String text,
|
||||||
String composeHint,
|
String composeHint,
|
||||||
CharacterCalculator characterCalculator)
|
CharacterCalculator characterCalculator)
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.drawable = drawable;
|
this.drawable = drawable;
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.composeHint = composeHint;
|
this.composeHint = composeHint;
|
||||||
this.characterCalculator = characterCalculator;
|
this.characterCalculator = characterCalculator;
|
||||||
@ -37,10 +42,6 @@ public class TransportOption {
|
|||||||
return this.type == type;
|
return this.type == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPlaintext() {
|
|
||||||
return type == Type.SMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSms() {
|
public boolean isSms() {
|
||||||
return type == Type.SMS;
|
return type == Type.SMS;
|
||||||
}
|
}
|
||||||
@ -49,10 +50,14 @@ public class TransportOption {
|
|||||||
return characterCalculator.calculateCharacters(charactersSpent);
|
return characterCalculator.calculateCharacters(charactersSpent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDrawable() {
|
public @DrawableRes int getDrawable() {
|
||||||
return drawable;
|
return drawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getBackgroundColor() {
|
||||||
|
return backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
public String getComposeHint() {
|
public String getComposeHint() {
|
||||||
return composeHint;
|
return composeHint;
|
||||||
}
|
}
|
||||||
|
@ -82,32 +82,28 @@ public class TransportOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<TransportOption> initializeAvailableTransports(boolean isMediaMessage) {
|
private List<TransportOption> initializeAvailableTransports(boolean isMediaMessage) {
|
||||||
List<TransportOption> results = new LinkedList<>();
|
List<TransportOption> results = new LinkedList<>();
|
||||||
int[] attributes = new int[]{R.attr.conversation_transport_sms_indicator,
|
|
||||||
R.attr.conversation_transport_push_indicator};
|
|
||||||
TypedArray iconArray = context.obtainStyledAttributes(attributes);
|
|
||||||
int smsIconResource = iconArray.getResourceId(0, -1);
|
|
||||||
int pushIconResource = iconArray.getResourceId(1, -1);
|
|
||||||
|
|
||||||
if (isMediaMessage) {
|
if (isMediaMessage) {
|
||||||
results.add(new TransportOption(Type.SMS, smsIconResource,
|
results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
|
||||||
|
context.getResources().getColor(R.color.grey_600),
|
||||||
context.getString(R.string.ConversationActivity_transport_insecure_mms),
|
context.getString(R.string.ConversationActivity_transport_insecure_mms),
|
||||||
context.getString(R.string.conversation_activity__type_message_mms_insecure),
|
context.getString(R.string.conversation_activity__type_message_mms_insecure),
|
||||||
new MmsCharacterCalculator()));
|
new MmsCharacterCalculator()));
|
||||||
} else {
|
} else {
|
||||||
results.add(new TransportOption(Type.SMS, smsIconResource,
|
results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
|
||||||
|
context.getResources().getColor(R.color.grey_600),
|
||||||
context.getString(R.string.ConversationActivity_transport_insecure_sms),
|
context.getString(R.string.ConversationActivity_transport_insecure_sms),
|
||||||
context.getString(R.string.conversation_activity__type_message_sms_insecure),
|
context.getString(R.string.conversation_activity__type_message_sms_insecure),
|
||||||
new SmsCharacterCalculator()));
|
new SmsCharacterCalculator()));
|
||||||
}
|
}
|
||||||
|
|
||||||
results.add(new TransportOption(Type.TEXTSECURE, pushIconResource,
|
results.add(new TransportOption(Type.TEXTSECURE, R.drawable.ic_send_push_white_24dp,
|
||||||
|
context.getResources().getColor(R.color.textsecure_primary),
|
||||||
context.getString(R.string.ConversationActivity_transport_textsecure),
|
context.getString(R.string.ConversationActivity_transport_textsecure),
|
||||||
context.getString(R.string.conversation_activity__type_message_push),
|
context.getString(R.string.conversation_activity__type_message_push),
|
||||||
new PushCharacterCalculator()));
|
new PushCharacterCalculator()));
|
||||||
|
|
||||||
iconArray.recycle();
|
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.PorterDuff.Mode;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -54,6 +55,7 @@ public class TransportOptionsAdapter extends BaseAdapter {
|
|||||||
ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
|
ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
|
||||||
TextView textView = (TextView) convertView.findViewById(R.id.text);
|
TextView textView = (TextView) convertView.findViewById(R.id.text);
|
||||||
|
|
||||||
|
imageView.getBackground().setColorFilter(transport.getBackgroundColor(), Mode.MULTIPLY);
|
||||||
imageView.setImageResource(transport.getDrawable());
|
imageView.setImageResource(transport.getDrawable());
|
||||||
textView.setText(transport.getDescription());
|
textView.setText(transport.getDescription());
|
||||||
|
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.Animator.AnimatorListener;
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.os.Build.VERSION;
|
||||||
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewAnimationUtils;
|
||||||
|
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
@ -20,6 +26,9 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
|||||||
private final PopupWindow popupWindow;
|
private final PopupWindow popupWindow;
|
||||||
private final SelectedListener listener;
|
private final SelectedListener listener;
|
||||||
|
|
||||||
|
private OnGlobalLayoutListener observer;
|
||||||
|
private View parent;
|
||||||
|
|
||||||
public TransportOptionsPopup(@NonNull Context context, @NonNull SelectedListener listener) {
|
public TransportOptionsPopup(@NonNull Context context, @NonNull SelectedListener listener) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.adapter = new TransportOptionsAdapter(context, new LinkedList<TransportOption>());
|
this.adapter = new TransportOptionsAdapter(context, new LinkedList<TransportOption>());
|
||||||
@ -27,7 +36,6 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
|||||||
View selectionMenu = LayoutInflater.from(context).inflate(R.layout.transport_selection, null);
|
View selectionMenu = LayoutInflater.from(context).inflate(R.layout.transport_selection, null);
|
||||||
ListView listView = (ListView) selectionMenu.findViewById(R.id.transport_selection_list);
|
ListView listView = (ListView) selectionMenu.findViewById(R.id.transport_selection_list);
|
||||||
|
|
||||||
|
|
||||||
listView.setAdapter(adapter);
|
listView.setAdapter(adapter);
|
||||||
|
|
||||||
this.popupWindow = new PopupWindow(selectionMenu);
|
this.popupWindow = new PopupWindow(selectionMenu);
|
||||||
@ -36,6 +44,10 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
|||||||
this.popupWindow.setOutsideTouchable(true);
|
this.popupWindow.setOutsideTouchable(true);
|
||||||
this.popupWindow.setWindowLayoutMode(0, WindowManager.LayoutParams.WRAP_CONTENT);
|
this.popupWindow.setWindowLayoutMode(0, WindowManager.LayoutParams.WRAP_CONTENT);
|
||||||
this.popupWindow.setWidth(context.getResources().getDimensionPixelSize(R.dimen.transport_selection_popup_width));
|
this.popupWindow.setWidth(context.getResources().getDimensionPixelSize(R.dimen.transport_selection_popup_width));
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
|
this.popupWindow.setAnimationStyle(0);
|
||||||
|
this.popupWindow.setElevation(context.getResources().getDimensionPixelSize(R.dimen.transport_selection_popup_yoff));
|
||||||
|
}
|
||||||
|
|
||||||
listView.setOnItemClickListener(this);
|
listView.setOnItemClickListener(this);
|
||||||
}
|
}
|
||||||
@ -48,17 +60,65 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
|||||||
final int yoff = context.getResources().getDimensionPixelOffset(R.dimen.transport_selection_popup_yoff);
|
final int yoff = context.getResources().getDimensionPixelOffset(R.dimen.transport_selection_popup_yoff);
|
||||||
|
|
||||||
popupWindow.showAsDropDown(parent, xoff, yoff);
|
popupWindow.showAsDropDown(parent, xoff, yoff);
|
||||||
|
animateInIfAvailable();
|
||||||
|
|
||||||
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
this.parent = parent;
|
||||||
|
this.observer = new OnGlobalLayoutListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onGlobalLayout() {
|
public void onGlobalLayout() {
|
||||||
popupWindow.update(parent, xoff, yoff, -1, -1);
|
popupWindow.update(parent, xoff, yoff, -1, -1);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
parent.getViewTreeObserver().addOnGlobalLayoutListener(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(VERSION_CODES.LOLLIPOP) private Animator getCircularReveal(View v, boolean in) {
|
||||||
|
int outBound = Math.max(v.getWidth(), v.getHeight());
|
||||||
|
return ViewAnimationUtils.createCircularReveal(v,
|
||||||
|
v.getMeasuredWidth(),
|
||||||
|
v.getMeasuredHeight(),
|
||||||
|
in ? 0 : outBound,
|
||||||
|
in ? outBound : 0)
|
||||||
|
.setDuration(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateInIfAvailable() {
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
|
popupWindow.getContentView().getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
|
||||||
|
@Override @TargetApi(VERSION_CODES.LOLLIPOP) public void onGlobalLayout() {
|
||||||
|
parent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||||
|
if (popupWindow.getContentView().isAttachedToWindow()) {
|
||||||
|
getCircularReveal(popupWindow.getContentView(), true).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateOutIfAvailable() {
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
|
Animator animator = getCircularReveal(popupWindow.getContentView(), false);
|
||||||
|
animator.addListener(new AnimatorListener() {
|
||||||
|
@Override public void onAnimationStart(Animator animation) {}
|
||||||
|
@Override public void onAnimationCancel(Animator animation) {}
|
||||||
|
@Override public void onAnimationRepeat(Animator animation) {}
|
||||||
|
@Override public void onAnimationEnd(Animator animation) {
|
||||||
|
popupWindow.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
animator.start();
|
||||||
|
} else {
|
||||||
|
popupWindow.dismiss();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dismiss() {
|
public void dismiss() {
|
||||||
this.popupWindow.dismiss();
|
animateOutIfAvailable();
|
||||||
|
if (this.observer != null && this.parent != null) {
|
||||||
|
parent.getViewTreeObserver().removeGlobalOnLayoutListener(observer);
|
||||||
|
}
|
||||||
|
this.observer = null;
|
||||||
|
this.parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -67,7 +127,7 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface SelectedListener {
|
public interface SelectedListener {
|
||||||
public void onSelected(TransportOption option);
|
void onSelected(TransportOption option);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,13 @@ import android.util.AttributeSet;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationSet;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
import android.view.animation.TranslateAnimation;
|
import android.view.animation.TranslateAnimation;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
|
||||||
public class AnimatingToggle extends FrameLayout {
|
public class AnimatingToggle extends FrameLayout {
|
||||||
|
|
||||||
private static final int SPEED_MILLIS = 200;
|
private static final int SPEED_MILLIS = 200;
|
||||||
@ -38,29 +42,19 @@ public class AnimatingToggle extends FrameLayout {
|
|||||||
} else {
|
} else {
|
||||||
child.setVisibility(View.GONE);
|
child.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
child.setClickable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void display(View view) {
|
public void display(View view) {
|
||||||
if (view == current) return;
|
if (view == current) return;
|
||||||
|
|
||||||
int oldViewIndex = getViewIndex(current);
|
animateOut(current, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_out));
|
||||||
int newViewIndex = getViewIndex(view);
|
animateIn(view, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_in));
|
||||||
|
|
||||||
int sign;
|
|
||||||
|
|
||||||
if (oldViewIndex < newViewIndex) sign = -1;
|
|
||||||
else sign = 1;
|
|
||||||
|
|
||||||
TranslateAnimation oldViewAnimation = createTranslation(0.0f, sign * 1.0f);
|
|
||||||
TranslateAnimation newViewAnimation = createTranslation(sign * -1.0f, 0.0f);
|
|
||||||
|
|
||||||
animateOut(current, oldViewAnimation);
|
|
||||||
animateIn(view, newViewAnimation);
|
|
||||||
|
|
||||||
current = view;
|
current = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateOut(final View view, TranslateAnimation animation) {
|
private void animateOut(final View view, Animation animation) {
|
||||||
animation.setAnimationListener(new Animation.AnimationListener() {
|
animation.setAnimationListener(new Animation.AnimationListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationStart(Animation animation) {
|
public void onAnimationStart(Animation animation) {
|
||||||
@ -79,7 +73,7 @@ public class AnimatingToggle extends FrameLayout {
|
|||||||
view.startAnimation(animation);
|
view.startAnimation(animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateIn(View view, TranslateAnimation animation) {
|
private void animateIn(View view, Animation animation) {
|
||||||
animation.setInterpolator(new FastOutSlowInInterpolator());
|
animation.setInterpolator(new FastOutSlowInInterpolator());
|
||||||
view.setVisibility(View.VISIBLE);
|
view.setVisibility(View.VISIBLE);
|
||||||
view.startAnimation(animation);
|
view.startAnimation(animation);
|
||||||
@ -92,17 +86,4 @@ public class AnimatingToggle extends FrameLayout {
|
|||||||
|
|
||||||
throw new IllegalArgumentException("Not a parent of this view.");
|
throw new IllegalArgumentException("Not a parent of this view.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private TranslateAnimation createTranslation(float startY, float endY) {
|
|
||||||
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
|
||||||
Animation.RELATIVE_TO_SELF, 0.0f,
|
|
||||||
Animation.RELATIVE_TO_SELF, startY,
|
|
||||||
Animation.RELATIVE_TO_SELF, endY);
|
|
||||||
|
|
||||||
translateAnimation.setDuration(SPEED_MILLIS);
|
|
||||||
translateAnimation.setInterpolator(new FastOutSlowInInterpolator());
|
|
||||||
|
|
||||||
return translateAnimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|