mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-25 13:58:40 +00:00
Refactor contact photo logic to not reuse drawables.
// FREEBIE
This commit is contained in:
@@ -1,151 +0,0 @@
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
import com.makeramen.roundedimageview.RoundedDrawable;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ContactPhotoFactory {
|
||||
private static final String TAG = ContactPhotoFactory.class.getSimpleName();
|
||||
|
||||
private static final ColorGenerator COLOR_GENERATOR = ColorGenerator.MATERIAL;
|
||||
private static final int UNKNOWN_COLOR = 0xff9E9E9E;
|
||||
|
||||
private static final Object defaultPhotoLock = new Object();
|
||||
private static final Object defaultGroupPhotoLock = new Object();
|
||||
private static final Object loadingPhotoLock = new Object();
|
||||
|
||||
private static Drawable defaultContactPhoto;
|
||||
private static Drawable defaultGroupContactPhoto;
|
||||
private static Drawable loadingPhoto;
|
||||
|
||||
private static final Map<Uri,Bitmap> localUserContactPhotoCache =
|
||||
Collections.synchronizedMap(new LRUCache<Uri,Bitmap>(2));
|
||||
|
||||
public static Drawable getLoadingPhoto(Context context) {
|
||||
synchronized (loadingPhotoLock) {
|
||||
if (loadingPhoto == null)
|
||||
loadingPhoto = RoundedDrawable.fromDrawable(context.getResources().getDrawable(android.R.color.transparent));
|
||||
|
||||
return loadingPhoto;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getDefaultContactPhoto(Context context, @Nullable String name) {
|
||||
int targetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
return TextDrawable.builder().beginConfig()
|
||||
.width(targetSize)
|
||||
.height(targetSize)
|
||||
.endConfig()
|
||||
.buildRound(String.valueOf(name.charAt(0)),
|
||||
COLOR_GENERATOR.getColor(name));
|
||||
}
|
||||
|
||||
synchronized (defaultPhotoLock) {
|
||||
if (defaultContactPhoto == null)
|
||||
defaultContactPhoto = TextDrawable.builder().beginConfig()
|
||||
.width(targetSize)
|
||||
.height(targetSize)
|
||||
.endConfig()
|
||||
.buildRound("#", UNKNOWN_COLOR);
|
||||
|
||||
return defaultContactPhoto;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getDefaultGroupPhoto(Context context) {
|
||||
synchronized (defaultGroupPhotoLock) {
|
||||
if (defaultGroupContactPhoto == null) {
|
||||
Drawable background = TextDrawable.builder().buildRound(" ", UNKNOWN_COLOR);
|
||||
RoundedDrawable foreground = (RoundedDrawable) RoundedDrawable.fromDrawable(context.getResources().getDrawable(R.drawable.ic_group_white_24dp));
|
||||
foreground.setScaleType(ImageView.ScaleType.CENTER);
|
||||
|
||||
|
||||
defaultGroupContactPhoto = new ExpandingLayerDrawable(new Drawable[] {background, foreground});
|
||||
}
|
||||
|
||||
return defaultGroupContactPhoto;
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
localUserContactPhotoCache.clear();
|
||||
}
|
||||
|
||||
public static Drawable getContactPhoto(Context context, Uri uri, String name) {
|
||||
final InputStream inputStream = getContactPhotoStream(context, uri);
|
||||
final int targetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
|
||||
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
return RoundedDrawable.fromBitmap(BitmapUtil.createScaledBitmap(inputStream,
|
||||
getContactPhotoStream(context, uri),
|
||||
targetSize,
|
||||
targetSize))
|
||||
.setScaleType(ImageView.ScaleType.CENTER_CROP)
|
||||
.setOval(true);
|
||||
} catch (BitmapDecodingException bde) {
|
||||
Log.w(TAG, bde);
|
||||
}
|
||||
}
|
||||
|
||||
return getDefaultContactPhoto(context, name);
|
||||
}
|
||||
|
||||
public static Drawable getGroupContactPhoto(Context context, @Nullable byte[] avatar) {
|
||||
if (avatar == null) return getDefaultGroupPhoto(context);
|
||||
|
||||
return RoundedDrawable.fromBitmap(BitmapFactory.decodeByteArray(avatar, 0, avatar.length))
|
||||
.setScaleType(ImageView.ScaleType.CENTER_CROP)
|
||||
.setOval(true);
|
||||
}
|
||||
|
||||
private static InputStream getContactPhotoStream(Context context, Uri uri) {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
return ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri, true);
|
||||
} else {
|
||||
return ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExpandingLayerDrawable extends LayerDrawable {
|
||||
|
||||
public ExpandingLayerDrawable(Drawable[] layers) {
|
||||
super(layers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class ContactSelectionListItem extends RelativeLayout implements Recipien
|
||||
|
||||
private void setContactPhotoImage(@Nullable Recipient recipient) {
|
||||
if (recipient!= null) {
|
||||
contactPhotoImage.setImageDrawable(recipient.getContactPhoto());
|
||||
contactPhotoImage.setImageDrawable(recipient.getContactPhoto().asDrawable(getContext()));
|
||||
recipient.addListener(this);
|
||||
} else {
|
||||
contactPhotoImage.setImageDrawable(null);
|
||||
@@ -111,7 +111,7 @@ public class ContactSelectionListItem extends RelativeLayout implements Recipien
|
||||
this.contactPhotoImage.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
contactPhotoImage.setImageDrawable(recipient.getContactPhoto());
|
||||
contactPhotoImage.setImageDrawable(recipient.getContactPhoto().asDrawable(getContext()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.thoughtcrime.securesms.contacts.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.makeramen.roundedimageview.RoundedDrawable;
|
||||
|
||||
public class BitmapContactPhoto implements ContactPhoto {
|
||||
|
||||
private final Bitmap bitmap;
|
||||
|
||||
BitmapContactPhoto(Bitmap bitmap) {
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable asDrawable(Context context) {
|
||||
return RoundedDrawable.fromBitmap(bitmap)
|
||||
.setScaleType(ImageView.ScaleType.CENTER_CROP)
|
||||
.setOval(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.thoughtcrime.securesms.contacts.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public interface ContactPhoto {
|
||||
|
||||
public Drawable asDrawable(Context context);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.thoughtcrime.securesms.contacts.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ContactPhotoFactory {
|
||||
private static final String TAG = ContactPhotoFactory.class.getSimpleName();
|
||||
|
||||
private static final int UNKNOWN_COLOR = 0xff9E9E9E;
|
||||
|
||||
public static ContactPhoto getLoadingPhoto() {
|
||||
return new TransparentContactPhoto();
|
||||
}
|
||||
|
||||
public static ContactPhoto getDefaultContactPhoto(@Nullable String name) {
|
||||
if (!TextUtils.isEmpty(name)) return new GeneratedContactPhoto(name);
|
||||
else return new GeneratedContactPhoto("#", UNKNOWN_COLOR);
|
||||
}
|
||||
|
||||
public static ContactPhoto getDefaultGroupPhoto() {
|
||||
return new ResourceContactPhoto(R.drawable.ic_group_white_24dp, UNKNOWN_COLOR);
|
||||
}
|
||||
|
||||
public static ContactPhoto getContactPhoto(Context context, Uri uri, String name) {
|
||||
try {
|
||||
InputStream inputStream = getContactPhotoStream(context, uri);
|
||||
int targetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
|
||||
|
||||
if (inputStream != null) {
|
||||
return new BitmapContactPhoto(BitmapUtil.createScaledBitmap(inputStream, getContactPhotoStream(context, uri), targetSize, targetSize));
|
||||
}
|
||||
} catch (BitmapDecodingException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
return getDefaultContactPhoto(name);
|
||||
}
|
||||
|
||||
public static ContactPhoto getGroupContactPhoto(@Nullable byte[] avatar) {
|
||||
if (avatar == null) return getDefaultGroupPhoto();
|
||||
|
||||
return new BitmapContactPhoto(BitmapFactory.decodeByteArray(avatar, 0, avatar.length));
|
||||
}
|
||||
|
||||
private static InputStream getContactPhotoStream(Context context, Uri uri) {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
return ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri, true);
|
||||
} else {
|
||||
return ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.thoughtcrime.securesms.contacts.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public class GeneratedContactPhoto implements ContactPhoto {
|
||||
|
||||
private final String name;
|
||||
private final int color;
|
||||
|
||||
GeneratedContactPhoto(@NonNull String name) {
|
||||
this(name, ColorGenerator.MATERIAL.getColor(name));
|
||||
}
|
||||
|
||||
GeneratedContactPhoto(@NonNull String name, int color) {
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable asDrawable(Context context) {
|
||||
int targetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
|
||||
|
||||
return TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.width(targetSize)
|
||||
.height(targetSize)
|
||||
.endConfig()
|
||||
.buildRound(String.valueOf(name.charAt(0)), color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.thoughtcrime.securesms.contacts.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.makeramen.roundedimageview.RoundedDrawable;
|
||||
|
||||
public class ResourceContactPhoto implements ContactPhoto {
|
||||
|
||||
private final int resourceId;
|
||||
private final int color;
|
||||
|
||||
ResourceContactPhoto(int resourceId, int color) {
|
||||
this.resourceId = resourceId;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable asDrawable(Context context) {
|
||||
Drawable background = TextDrawable.builder().buildRound(" ", color);
|
||||
RoundedDrawable foreground = (RoundedDrawable) RoundedDrawable.fromDrawable(context.getResources().getDrawable(resourceId));
|
||||
foreground.setScaleType(ImageView.ScaleType.CENTER);
|
||||
|
||||
return new ExpandingLayerDrawable(new Drawable[] {background, foreground});
|
||||
}
|
||||
|
||||
private static class ExpandingLayerDrawable extends LayerDrawable {
|
||||
public ExpandingLayerDrawable(Drawable[] layers) {
|
||||
super(layers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.thoughtcrime.securesms.contacts.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.makeramen.roundedimageview.RoundedDrawable;
|
||||
|
||||
public class TransparentContactPhoto implements ContactPhoto {
|
||||
|
||||
TransparentContactPhoto() {}
|
||||
|
||||
@Override
|
||||
public Drawable asDrawable(Context context) {
|
||||
return RoundedDrawable.fromDrawable(context.getResources().getDrawable(android.R.color.transparent));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user