mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-16 05:21:26 +00:00
parent
4314a4b42b
commit
61386e9ca9
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB |
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<bitmap android:src="@drawable/ic_badge_24dp"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:gravity="bottom|right"
|
|
||||||
android:tileMode="disabled" />
|
|
@ -18,7 +18,6 @@
|
|||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:foreground="@drawable/contact_photo_background"
|
android:foreground="@drawable/contact_photo_background"
|
||||||
android:cropToPadding="true"
|
android:cropToPadding="true"
|
||||||
app:showBadge="true"
|
|
||||||
tools:src="@color/md_material_blue_600"
|
tools:src="@color/md_material_blue_600"
|
||||||
android:layout_marginRight="10dp"
|
android:layout_marginRight="10dp"
|
||||||
android:contentDescription="@string/SingleContactSelectionActivity_contact_photo" />
|
android:contentDescription="@string/SingleContactSelectionActivity_contact_photo" />
|
||||||
|
@ -132,7 +132,6 @@
|
|||||||
|
|
||||||
<declare-styleable name="AvatarImageView">
|
<declare-styleable name="AvatarImageView">
|
||||||
<attr name="inverted" format="boolean" />
|
<attr name="inverted" format="boolean" />
|
||||||
<attr name="showBadge" format="boolean" />
|
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="ThumbnailView">
|
<declare-styleable name="ThumbnailView">
|
||||||
|
@ -3,13 +3,8 @@ package org.thoughtcrime.securesms.components;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.support.v4.util.Pair;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@ -21,13 +16,10 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
|||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
|
||||||
import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities.Capability;
|
|
||||||
|
|
||||||
public class AvatarImageView extends ImageView {
|
public class AvatarImageView extends ImageView {
|
||||||
|
|
||||||
private boolean inverted;
|
private boolean inverted;
|
||||||
private boolean showBadge;
|
|
||||||
|
|
||||||
public AvatarImageView(Context context) {
|
public AvatarImageView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -41,7 +33,6 @@ public class AvatarImageView extends ImageView {
|
|||||||
if (attrs != null) {
|
if (attrs != null) {
|
||||||
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AvatarImageView, 0, 0);
|
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AvatarImageView, 0, 0);
|
||||||
inverted = typedArray.getBoolean(0, false);
|
inverted = typedArray.getBoolean(0, false);
|
||||||
showBadge = typedArray.getBoolean(1, false);
|
|
||||||
typedArray.recycle();
|
typedArray.recycle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,12 +42,9 @@ public class AvatarImageView extends ImageView {
|
|||||||
MaterialColor backgroundColor = recipients.getColor();
|
MaterialColor backgroundColor = recipients.getColor();
|
||||||
setImageDrawable(recipients.getContactPhoto().asDrawable(getContext(), backgroundColor.toConversationColor(getContext()), inverted));
|
setImageDrawable(recipients.getContactPhoto().asDrawable(getContext(), backgroundColor.toConversationColor(getContext()), inverted));
|
||||||
setAvatarClickHandler(recipients, quickContactEnabled);
|
setAvatarClickHandler(recipients, quickContactEnabled);
|
||||||
setTag(recipients);
|
|
||||||
if (showBadge) new BadgeResolutionTask(getContext()).execute(recipients);
|
|
||||||
} else {
|
} else {
|
||||||
setImageDrawable(ContactPhotoFactory.getDefaultContactPhoto(null).asDrawable(getContext(), ContactColors.UNKNOWN_COLOR.toConversationColor(getContext()), inverted));
|
setImageDrawable(ContactPhotoFactory.getDefaultContactPhoto(null).asDrawable(getContext(), ContactColors.UNKNOWN_COLOR.toConversationColor(getContext()), inverted));
|
||||||
setOnClickListener(null);
|
setOnClickListener(null);
|
||||||
setTag(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,30 +73,4 @@ public class AvatarImageView extends ImageView {
|
|||||||
setOnClickListener(null);
|
setOnClickListener(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BadgeResolutionTask extends AsyncTask<Recipients,Void,Pair<Recipients, Boolean>> {
|
|
||||||
private final Context context;
|
|
||||||
|
|
||||||
public BadgeResolutionTask(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Pair<Recipients, Boolean> doInBackground(Recipients... recipients) {
|
|
||||||
Capability textCapability = DirectoryHelper.getUserCapabilities(context, recipients[0]).getTextCapability();
|
|
||||||
return new Pair<>(recipients[0], textCapability == Capability.SUPPORTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Pair<Recipients, Boolean> result) {
|
|
||||||
if (getTag() == result.first && result.second) {
|
|
||||||
final Drawable badged = new LayerDrawable(new Drawable[] {
|
|
||||||
getDrawable(),
|
|
||||||
ContextCompat.getDrawable(context, R.drawable.badge_drawable)
|
|
||||||
});
|
|
||||||
|
|
||||||
setImageDrawable(badged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import android.annotation.TargetApi;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build.VERSION;
|
import android.os.Build.VERSION;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.view.ViewCompat;
|
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@ -57,8 +56,8 @@ public class RecyclerViewFastScroller extends LinearLayout {
|
|||||||
return;
|
return;
|
||||||
final int verticalScrollOffset = recyclerView.computeVerticalScrollOffset();
|
final int verticalScrollOffset = recyclerView.computeVerticalScrollOffset();
|
||||||
final int verticalScrollRange = recyclerView.computeVerticalScrollRange();
|
final int verticalScrollRange = recyclerView.computeVerticalScrollRange();
|
||||||
float proportion = (float)verticalScrollOffset / ((float)verticalScrollRange - height);
|
final float proportion = (float)verticalScrollOffset / verticalScrollRange;
|
||||||
setBubbleAndHandlePosition(height * proportion);
|
setBubbleAndHandlePosition(proportion);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,7 +105,7 @@ public class RecyclerViewFastScroller extends LinearLayout {
|
|||||||
handle.setSelected(true);
|
handle.setSelected(true);
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
final float y = event.getY();
|
final float y = event.getY();
|
||||||
setBubbleAndHandlePosition(y);
|
setBubbleAndHandlePosition(y / height);
|
||||||
setRecyclerViewPosition(y);
|
setRecyclerViewPosition(y);
|
||||||
return true;
|
return true;
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
@ -147,12 +146,14 @@ public class RecyclerViewFastScroller extends LinearLayout {
|
|||||||
if (recyclerView != null) {
|
if (recyclerView != null) {
|
||||||
final int itemCount = recyclerView.getAdapter().getItemCount();
|
final int itemCount = recyclerView.getAdapter().getItemCount();
|
||||||
float proportion;
|
float proportion;
|
||||||
if (ViewUtil.getY(handle) == 0)
|
if (ViewUtil.getY(handle) == 0) {
|
||||||
proportion = 0f;
|
proportion = 0f;
|
||||||
else if (ViewUtil.getY(handle) + handle.getHeight() >= height - TRACK_SNAP_RANGE)
|
} else if (ViewUtil.getY(handle) + handle.getHeight() >= height - TRACK_SNAP_RANGE) {
|
||||||
proportion = 1f;
|
proportion = 1f;
|
||||||
else
|
} else {
|
||||||
proportion = y / (float) height;
|
proportion = y / (float)height;
|
||||||
|
}
|
||||||
|
|
||||||
final int targetPos = Util.clamp((int)(proportion * (float)itemCount), 0, itemCount - 1);
|
final int targetPos = Util.clamp((int)(proportion * (float)itemCount), 0, itemCount - 1);
|
||||||
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(targetPos, 0);
|
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(targetPos, 0);
|
||||||
final CharSequence bubbleText = ((FastScrollAdapter) recyclerView.getAdapter()).getBubbleText(targetPos);
|
final CharSequence bubbleText = ((FastScrollAdapter) recyclerView.getAdapter()).getBubbleText(targetPos);
|
||||||
@ -164,8 +165,11 @@ public class RecyclerViewFastScroller extends LinearLayout {
|
|||||||
private void setBubbleAndHandlePosition(float y) {
|
private void setBubbleAndHandlePosition(float y) {
|
||||||
final int handleHeight = handle.getHeight();
|
final int handleHeight = handle.getHeight();
|
||||||
final int bubbleHeight = bubble.getHeight();
|
final int bubbleHeight = bubble.getHeight();
|
||||||
ViewUtil.setY(handle, Util.clamp((int)(y - handleHeight / 2), 0, height - handleHeight));
|
final int handleY = Util.clamp((int)((height - handleHeight) * y), 0, height - handleHeight);
|
||||||
ViewUtil.setY(bubble, Util.clamp((int)(y - bubbleHeight), 0, height - bubbleHeight - handleHeight / 2));
|
ViewUtil.setY(handle, handleY);
|
||||||
|
ViewUtil.setY(bubble, Util.clamp(handleY - bubbleHeight - bubble.getPaddingBottom() + handleHeight,
|
||||||
|
0,
|
||||||
|
height - bubbleHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(11)
|
@TargetApi(11)
|
||||||
|
@ -20,14 +20,13 @@ import android.content.Context;
|
|||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.support.annotation.DrawableRes;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.ImageSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
@ -40,6 +39,7 @@ import org.thoughtcrime.securesms.ContactSelectionListFragment.StickyHeaderAdapt
|
|||||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.HeaderViewHolder;
|
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.HeaderViewHolder;
|
||||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.ViewHolder;
|
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.ViewHolder;
|
||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||||
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -103,7 +103,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getHeaderId(int i) {
|
public long getHeaderId(int i) {
|
||||||
return getHeaderString(i).hashCode();
|
return Util.hashCode(getHeaderString(i), isPush(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -137,36 +137,33 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
|
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
|
||||||
((TextView)viewHolder.itemView).setText(getSpannedHeaderString(position, R.drawable.ic_signal_grey_24dp));
|
((TextView)viewHolder.itemView).setText(getSpannedHeaderString(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getBubbleText(int position) {
|
public CharSequence getBubbleText(int position) {
|
||||||
return getSpannedHeaderString(position, R.drawable.ic_signal_white_48dp);
|
return getHeaderString(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Long, String> getSelectedContacts() {
|
public Map<Long, String> getSelectedContacts() {
|
||||||
return selectedContacts;
|
return selectedContacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence getSpannedHeaderString(int position, @DrawableRes int drawable) {
|
private CharSequence getSpannedHeaderString(int position) {
|
||||||
Cursor cursor = getCursorAtPositionOrThrow(position);
|
final String headerString = getHeaderString(position);
|
||||||
|
if (isPush(position)) {
|
||||||
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.PUSH_TYPE) {
|
SpannableString spannable = new SpannableString(headerString);
|
||||||
SpannableString spannable = new SpannableString(" ");
|
spannable.setSpan(new ForegroundColorSpan(getContext().getResources().getColor(R.color.signal_primary)), 0, headerString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
spannable.setSpan(new ImageSpan(getContext(), drawable, ImageSpan.ALIGN_BOTTOM), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
return spannable;
|
return spannable;
|
||||||
} else {
|
} else {
|
||||||
return getHeaderString(position);
|
return headerString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NonNull String getHeaderString(int position) {
|
private @NonNull String getHeaderString(int position) {
|
||||||
Cursor cursor = getCursorAtPositionOrThrow(position);
|
Cursor cursor = getCursorAtPositionOrThrow(position);
|
||||||
String letter = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
|
String letter = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
|
||||||
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.PUSH_TYPE) {
|
if (!TextUtils.isEmpty(letter)) {
|
||||||
return getContext().getString(R.string.app_name);
|
|
||||||
} else if (!TextUtils.isEmpty(letter)) {
|
|
||||||
String firstChar = letter.trim().substring(0, 1).toUpperCase();
|
String firstChar = letter.trim().substring(0, 1).toUpperCase();
|
||||||
if (Character.isLetterOrDigit(firstChar.codePointAt(0))) {
|
if (Character.isLetterOrDigit(firstChar.codePointAt(0))) {
|
||||||
return firstChar;
|
return firstChar;
|
||||||
@ -176,12 +173,19 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
|
|||||||
return "#";
|
return "#";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPush(int position) {
|
||||||
|
final Cursor cursor = getCursorAtPositionOrThrow(position);
|
||||||
|
return cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.PUSH_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
private Cursor getCursorAtPositionOrThrow(int position) {
|
private Cursor getCursorAtPositionOrThrow(int position) {
|
||||||
Cursor cursor = getCursor();
|
Cursor cursor = getCursor();
|
||||||
if (cursor == null) {
|
if (cursor == null) {
|
||||||
throw new IllegalStateException("Cursor should not be null here.");
|
throw new IllegalStateException("Cursor should not be null here.");
|
||||||
}
|
}
|
||||||
if (!cursor.moveToPosition(position));
|
if (!cursor.moveToPosition(position)) {
|
||||||
|
throw new IllegalStateException("Cursor couldn't be moved to position.");
|
||||||
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user