From 62873ee77389489475681c7ca40d56ad504d05b1 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Thu, 8 Aug 2024 17:04:59 +1000 Subject: [PATCH] Removed com.amulyakhare.textdrawable Cleaned up references to TextDrawable. Also cleaned up the way we load layered drawables, used in ProfilePictureView for the load state as the icons were stretched across and didn't look nice. --- app/src/main/AndroidManifest.xml | 2 +- .../securesms/calls/WebRtcCallActivity.kt | 8 - .../securesms/components/AvatarImageView.java | 198 ------------------ .../components/ProfilePictureView.kt | 7 +- .../SingleRecipientNotificationBuilder.java | 8 +- libsession/build.gradle | 1 - .../avatars/FallbackContactPhoto.java | 2 +- .../avatars/GeneratedContactPhoto.java | 83 -------- .../avatars/ResourceContactPhoto.java | 32 ++- .../avatars/TransparentContactPhoto.java | 10 +- 10 files changed, 41 insertions(+), 310 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java delete mode 100644 libsession/src/main/java/org/session/libsession/avatars/GeneratedContactPhoto.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d70c9e080e..9ed5bc0b53 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> - + { - if (recipient.getContactUri() != null) { - ContactsContract.QuickContact.showQuickContact(getContext(), AvatarImageView.this, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null); - } else { - getContext().startActivity(RecipientExporter.export(recipient).asAddContactIntent()); - } - }); - } else { - super.setOnClickListener(listener); - } - } - - private static class RecipientContactPhoto { - - private final @NonNull Recipient recipient; - private final @Nullable ContactPhoto contactPhoto; - private final boolean ready; - - RecipientContactPhoto(@NonNull Recipient recipient) { - this.recipient = recipient; - this.ready = !recipient.isResolving(); - this.contactPhoto = recipient.getContactPhoto(); - } - - public boolean equals(@Nullable RecipientContactPhoto other) { - if (other == null) return false; - - return other.recipient.equals(recipient) && - other.recipient.getColor().equals(recipient.getColor()) && - other.ready == ready && - Objects.equals(other.contactPhoto, contactPhoto); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt index 6d59bbfc92..5ec9bc096c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt @@ -38,10 +38,13 @@ class ProfilePictureView @JvmOverloads constructor( var additionalDisplayName: String? = null private val profilePicturesCache = mutableMapOf() + private val resourcePadding by lazy { + context.resources.getDimensionPixelSize(R.dimen.normal_padding).toFloat() + } private val unknownRecipientDrawable by lazy { ResourceContactPhoto(R.drawable.ic_profile_default) - .asDrawable(context, ContactColors.UNKNOWN_COLOR.toConversationColor(context), false) } + .asDrawable(context, ContactColors.UNKNOWN_COLOR.toConversationColor(context), false, resourcePadding) } private val unknownOpenGroupDrawable by lazy { ResourceContactPhoto(R.drawable.ic_notification) - .asDrawable(context, ContactColors.UNKNOWN_COLOR.toConversationColor(context), false) } + .asDrawable(context, ContactColors.UNKNOWN_COLOR.toConversationColor(context), false, resourcePadding) } constructor(context: Context, sender: Recipient): this(context) { update(sender) diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java index d5aeba6022..146021ac68 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java @@ -28,7 +28,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy; import org.session.libsession.avatars.ContactColors; import org.session.libsession.avatars.ContactPhoto; -import org.session.libsession.avatars.GeneratedContactPhoto; +import org.session.libsession.avatars.ResourceContactPhoto; import org.session.libsession.messaging.contacts.Contact; import org.session.libsession.utilities.NotificationPrivacyPreference; import org.session.libsession.utilities.TextSecurePreferences; @@ -60,6 +60,8 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil private CharSequence contentTitle; private CharSequence contentText; + private static final Integer ICON_SIZE = 128; + public SingleRecipientNotificationBuilder(@NonNull Context context, @NonNull NotificationPrivacyPreference privacy) { super(context, privacy); @@ -108,7 +110,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil } else { setContentTitle(context.getString(R.string.SingleRecipientNotificationBuilder_signal)); - setLargeIcon(new GeneratedContactPhoto("Unknown", R.drawable.ic_profile_default).asDrawable(context, ContactColors.UNKNOWN_COLOR.toConversationColor(context))); + setLargeIcon(AvatarPlaceholderGenerator.generate(context, ICON_SIZE, "", "Unknown")); } } @@ -330,7 +332,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil private static Drawable getPlaceholderDrawable(Context context, Recipient recipient) { String publicKey = recipient.getAddress().serialize(); String displayName = recipient.getName(); - return AvatarPlaceholderGenerator.generate(context, 128, publicKey, displayName); + return AvatarPlaceholderGenerator.generate(context, ICON_SIZE, publicKey, displayName); } /** diff --git a/libsession/build.gradle b/libsession/build.gradle index 55146823ec..417b464ca9 100644 --- a/libsession/build.gradle +++ b/libsession/build.gradle @@ -32,7 +32,6 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' implementation "com.github.bumptech.glide:glide:$glideVersion" - implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'com.annimon:stream:1.1.8' implementation 'com.makeramen:roundedimageview:2.1.0' implementation 'com.esotericsoftware:kryo:5.1.1' diff --git a/libsession/src/main/java/org/session/libsession/avatars/FallbackContactPhoto.java b/libsession/src/main/java/org/session/libsession/avatars/FallbackContactPhoto.java index b2095c5980..9be08ea9ff 100644 --- a/libsession/src/main/java/org/session/libsession/avatars/FallbackContactPhoto.java +++ b/libsession/src/main/java/org/session/libsession/avatars/FallbackContactPhoto.java @@ -5,6 +5,6 @@ import android.graphics.drawable.Drawable; public interface FallbackContactPhoto { - public Drawable asDrawable(Context context, int color); public Drawable asDrawable(Context context, int color, boolean inverted); + public Drawable asDrawable(Context context, int color, boolean inverted, Float padding); } diff --git a/libsession/src/main/java/org/session/libsession/avatars/GeneratedContactPhoto.java b/libsession/src/main/java/org/session/libsession/avatars/GeneratedContactPhoto.java deleted file mode 100644 index 0f607d6e33..0000000000 --- a/libsession/src/main/java/org/session/libsession/avatars/GeneratedContactPhoto.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.session.libsession.avatars; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; -import android.text.TextUtils; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.amulyakhare.textdrawable.TextDrawable; - -import org.session.libsession.R; -import org.session.libsession.utilities.ThemeUtil; -import org.session.libsession.utilities.ViewUtil; - -import java.util.regex.Pattern; - -public class GeneratedContactPhoto implements FallbackContactPhoto { - - private static final Pattern PATTERN = Pattern.compile("[^\\p{L}\\p{Nd}\\p{S}]+"); - private static final Typeface TYPEFACE = Typeface.create("sans-serif-medium", Typeface.NORMAL); - - private final String name; - private final int fallbackResId; - - public GeneratedContactPhoto(@NonNull String name, @DrawableRes int fallbackResId) { - this.name = name; - this.fallbackResId = fallbackResId; - } - - @Override - public Drawable asDrawable(Context context, int color) { - return asDrawable(context, color,false); - } - - @Override - public Drawable asDrawable(Context context, int color, boolean inverted) { - int targetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size); - String character = getAbbreviation(name); - - if (!TextUtils.isEmpty(character)) { - Drawable base = TextDrawable.builder() - .beginConfig() - .width(targetSize) - .height(targetSize) - .useFont(TYPEFACE) - .fontSize(ViewUtil.dpToPx(context, 24)) - .textColor(inverted ? color : Color.WHITE) - .endConfig() - .buildRound(character, inverted ? Color.WHITE : color); - - Drawable gradient = context.getResources().getDrawable(ThemeUtil.isDarkTheme(context) ? R.drawable.avatar_gradient_dark - : R.drawable.avatar_gradient_light); - return new LayerDrawable(new Drawable[] { base, gradient }); - } - - return new ResourceContactPhoto(fallbackResId).asDrawable(context, color, inverted); - } - - private @Nullable String getAbbreviation(String name) { - String[] parts = name.split(" "); - StringBuilder builder = new StringBuilder(); - int count = 0; - - for (int i = 0; i < parts.length && count < 2; i++) { - String cleaned = PATTERN.matcher(parts[i]).replaceFirst(""); - if (!TextUtils.isEmpty(cleaned)) { - builder.appendCodePoint(cleaned.codePointAt(0)); - count++; - } - } - - if (builder.length() == 0) { - return null; - } else { - return builder.toString(); - } - } -} diff --git a/libsession/src/main/java/org/session/libsession/avatars/ResourceContactPhoto.java b/libsession/src/main/java/org/session/libsession/avatars/ResourceContactPhoto.java index 2920b4b1ce..f76135e95a 100644 --- a/libsession/src/main/java/org/session/libsession/avatars/ResourceContactPhoto.java +++ b/libsession/src/main/java/org/session/libsession/avatars/ResourceContactPhoto.java @@ -4,13 +4,13 @@ import android.content.Context; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; import android.widget.ImageView; import androidx.annotation.DrawableRes; import androidx.appcompat.content.res.AppCompatResources; -import com.amulyakhare.textdrawable.TextDrawable; import com.makeramen.roundedimageview.RoundedDrawable; import org.session.libsession.R; @@ -25,19 +25,33 @@ public class ResourceContactPhoto implements FallbackContactPhoto { } @Override - public Drawable asDrawable(Context context, int color) { - return asDrawable(context, color, false); + public Drawable asDrawable(Context context, int color, boolean inverted) { + return asDrawable(context, 0, false, 0f); } @Override - public Drawable asDrawable(Context context, int color, boolean inverted) { - Drawable background = TextDrawable.builder().buildRound(" ", inverted ? Color.WHITE : color); - RoundedDrawable foreground = (RoundedDrawable) RoundedDrawable.fromDrawable(AppCompatResources.getDrawable(context, resourceId)); + public Drawable asDrawable(Context context, int color, boolean inverted, Float padding) { + // rounded colored background + GradientDrawable background = new GradientDrawable(); + background.setShape(GradientDrawable.OVAL); + background.setColor(inverted ? Color.WHITE : color); - foreground.setScaleType(ImageView.ScaleType.CENTER_CROP); + // resource image in the foreground + RoundedDrawable foreground = (RoundedDrawable) RoundedDrawable.fromDrawable(AppCompatResources.getDrawable(context, resourceId)); - if (inverted) { - foreground.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + if (foreground != null) { + if(padding == 0f){ + foreground.setScaleType(ImageView.ScaleType.CENTER_CROP); + } else { + // apply padding via a transparent border oterhwise things get misaligned + foreground.setScaleType(ImageView.ScaleType.FIT_CENTER); + foreground.setBorderColor(Color.TRANSPARENT); + foreground.setBorderWidth(padding); + } + + if (inverted) { + foreground.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + } } Drawable gradient = AppCompatResources.getDrawable( diff --git a/libsession/src/main/java/org/session/libsession/avatars/TransparentContactPhoto.java b/libsession/src/main/java/org/session/libsession/avatars/TransparentContactPhoto.java index 56f2757e15..74d8e4ddc7 100644 --- a/libsession/src/main/java/org/session/libsession/avatars/TransparentContactPhoto.java +++ b/libsession/src/main/java/org/session/libsession/avatars/TransparentContactPhoto.java @@ -3,6 +3,8 @@ package org.session.libsession.avatars; import android.content.Context; import android.graphics.drawable.Drawable; +import androidx.core.content.ContextCompat; + import com.makeramen.roundedimageview.RoundedDrawable; public class TransparentContactPhoto implements FallbackContactPhoto { @@ -10,13 +12,13 @@ public class TransparentContactPhoto implements FallbackContactPhoto { public TransparentContactPhoto() {} @Override - public Drawable asDrawable(Context context, int color) { - return asDrawable(context, color, false); + public Drawable asDrawable(Context context, int color, boolean inverted) { + return asDrawable(context, color, inverted, 0f); } @Override - public Drawable asDrawable(Context context, int color, boolean inverted) { - return RoundedDrawable.fromDrawable(context.getResources().getDrawable(android.R.color.transparent)); + public Drawable asDrawable(Context context, int color, boolean inverted, Float padding) { + return RoundedDrawable.fromDrawable(ContextCompat.getDrawable(context, android.R.color.transparent)); } }