mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-25 00:31:54 +00:00
committed by
Moxie Marlinspike
parent
140cbe9f25
commit
daa98107c3
@@ -23,6 +23,11 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
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.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
@@ -30,6 +35,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
@@ -154,6 +160,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private View composePanel;
|
||||
private View composeBubble;
|
||||
|
||||
private AttachmentTypeSelectorAdapter attachmentAdapter;
|
||||
private AttachmentManager attachmentManager;
|
||||
@@ -732,6 +739,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
titleView = (ConversationTitleView) getSupportActionBar().getCustomView();
|
||||
unblockButton = (Button) findViewById(R.id.unblock_button);
|
||||
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);
|
||||
attachmentManager = new AttachmentManager(this, this);
|
||||
@@ -747,6 +761,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
public void onChange(TransportOption newTransport) {
|
||||
calculateCharactersRemaining();
|
||||
composeText.setHint(newTransport.getComposeHint());
|
||||
buttonToggle.getBackground().setColorFilter(newTransport.getBackgroundColor(), Mode.MULTIPLY);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.support.annotation.DrawableRes;
|
||||
|
||||
import org.thoughtcrime.securesms.util.CharacterCalculator;
|
||||
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
|
||||
|
||||
@@ -11,19 +13,22 @@ public class TransportOption {
|
||||
}
|
||||
|
||||
private int drawable;
|
||||
private int backgroundColor;
|
||||
private String text;
|
||||
private Type type;
|
||||
private String composeHint;
|
||||
private CharacterCalculator characterCalculator;
|
||||
|
||||
public TransportOption(Type type,
|
||||
int drawable,
|
||||
@DrawableRes int drawable,
|
||||
int backgroundColor,
|
||||
String text,
|
||||
String composeHint,
|
||||
CharacterCalculator characterCalculator)
|
||||
{
|
||||
this.type = type;
|
||||
this.drawable = drawable;
|
||||
this.backgroundColor = backgroundColor;
|
||||
this.text = text;
|
||||
this.composeHint = composeHint;
|
||||
this.characterCalculator = characterCalculator;
|
||||
@@ -37,10 +42,6 @@ public class TransportOption {
|
||||
return this.type == type;
|
||||
}
|
||||
|
||||
public boolean isPlaintext() {
|
||||
return type == Type.SMS;
|
||||
}
|
||||
|
||||
public boolean isSms() {
|
||||
return type == Type.SMS;
|
||||
}
|
||||
@@ -49,10 +50,14 @@ public class TransportOption {
|
||||
return characterCalculator.calculateCharacters(charactersSpent);
|
||||
}
|
||||
|
||||
public int getDrawable() {
|
||||
public @DrawableRes int getDrawable() {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public String getComposeHint() {
|
||||
return composeHint;
|
||||
}
|
||||
|
||||
@@ -82,32 +82,28 @@ public class TransportOptions {
|
||||
}
|
||||
|
||||
private List<TransportOption> initializeAvailableTransports(boolean isMediaMessage) {
|
||||
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);
|
||||
List<TransportOption> results = new LinkedList<>();
|
||||
|
||||
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.conversation_activity__type_message_mms_insecure),
|
||||
new MmsCharacterCalculator()));
|
||||
} 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.conversation_activity__type_message_sms_insecure),
|
||||
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.conversation_activity__type_message_push),
|
||||
new PushCharacterCalculator()));
|
||||
|
||||
iconArray.recycle();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -54,6 +55,7 @@ public class TransportOptionsAdapter extends BaseAdapter {
|
||||
ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
|
||||
TextView textView = (TextView) convertView.findViewById(R.id.text);
|
||||
|
||||
imageView.getBackground().setColorFilter(transport.getBackgroundColor(), Mode.MULTIPLY);
|
||||
imageView.setImageResource(transport.getDrawable());
|
||||
textView.setText(transport.getDescription());
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.Animator.AnimatorListener;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.ViewAnimationUtils;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
@@ -20,6 +26,9 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
||||
private final PopupWindow popupWindow;
|
||||
private final SelectedListener listener;
|
||||
|
||||
private OnGlobalLayoutListener observer;
|
||||
private View parent;
|
||||
|
||||
public TransportOptionsPopup(@NonNull Context context, @NonNull SelectedListener listener) {
|
||||
this.listener = listener;
|
||||
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);
|
||||
ListView listView = (ListView) selectionMenu.findViewById(R.id.transport_selection_list);
|
||||
|
||||
|
||||
listView.setAdapter(adapter);
|
||||
|
||||
this.popupWindow = new PopupWindow(selectionMenu);
|
||||
@@ -36,6 +44,10 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
||||
this.popupWindow.setOutsideTouchable(true);
|
||||
this.popupWindow.setWindowLayoutMode(0, WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
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);
|
||||
}
|
||||
@@ -48,17 +60,65 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
||||
final int yoff = context.getResources().getDimensionPixelOffset(R.dimen.transport_selection_popup_yoff);
|
||||
|
||||
popupWindow.showAsDropDown(parent, xoff, yoff);
|
||||
animateInIfAvailable();
|
||||
|
||||
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
this.parent = parent;
|
||||
this.observer = new OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
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() {
|
||||
this.popupWindow.dismiss();
|
||||
animateOutIfAvailable();
|
||||
if (this.observer != null && this.parent != null) {
|
||||
parent.getViewTreeObserver().removeGlobalOnLayoutListener(observer);
|
||||
}
|
||||
this.observer = null;
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,7 +127,7 @@ public class TransportOptionsPopup implements ListView.OnItemClickListener {
|
||||
}
|
||||
|
||||
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.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public class AnimatingToggle extends FrameLayout {
|
||||
|
||||
private static final int SPEED_MILLIS = 200;
|
||||
@@ -38,29 +42,19 @@ public class AnimatingToggle extends FrameLayout {
|
||||
} else {
|
||||
child.setVisibility(View.GONE);
|
||||
}
|
||||
child.setClickable(false);
|
||||
}
|
||||
|
||||
public void display(View view) {
|
||||
if (view == current) return;
|
||||
|
||||
int oldViewIndex = getViewIndex(current);
|
||||
int newViewIndex = getViewIndex(view);
|
||||
|
||||
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);
|
||||
animateOut(current, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_out));
|
||||
animateIn(view, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_in));
|
||||
|
||||
current = view;
|
||||
}
|
||||
|
||||
private void animateOut(final View view, TranslateAnimation animation) {
|
||||
private void animateOut(final View view, Animation animation) {
|
||||
animation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
@@ -79,7 +73,7 @@ public class AnimatingToggle extends FrameLayout {
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
private void animateIn(View view, TranslateAnimation animation) {
|
||||
private void animateIn(View view, Animation animation) {
|
||||
animation.setInterpolator(new FastOutSlowInInterpolator());
|
||||
view.setVisibility(View.VISIBLE);
|
||||
view.startAnimation(animation);
|
||||
@@ -92,17 +86,4 @@ public class AnimatingToggle extends FrameLayout {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user