diff --git a/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java index 4982c2605f6..bc8e2172d13 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/AvatarPreviewActivity.java @@ -3,8 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Bitmap; +import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.transition.TransitionInflater; @@ -15,7 +14,6 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityOptionsCompat; -import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import com.bumptech.glide.Glide; import com.bumptech.glide.load.DataSource; @@ -109,31 +107,32 @@ protected void onCreate(Bundle savedInstanceState, boolean ready) { Drawable fallbackDrawable = new FallbackAvatarDrawable(context, fallbackAvatar); - Resources resources = this.getResources(); - + // Not asBitmap(), so an animated GIF avatar can actually play here. Glide.with(this) - .asBitmap() .load(contactPhoto) .fallback(fallbackDrawable) .error(fallbackDrawable) .diskCacheStrategy(DiskCacheStrategy.ALL) - .addListener(new RequestListener() { + .addListener(new RequestListener() { @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { Log.w(TAG, "Unable to load avatar, or avatar removed, closing"); finish(); return false; } @Override - public boolean onResourceReady(Bitmap resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { return false; } }) - .into(new CustomTarget() { + .into(new CustomTarget() { @Override - public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { - avatar.setImageDrawable(RoundedBitmapDrawableFactory.create(resources, resource)); + public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { + avatar.setImageDrawable(resource); + if (resource instanceof Animatable) { + ((Animatable) resource).start(); + } startPostponedEnterTransition(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/avatar/view/AvatarView.kt b/app/src/main/java/org/thoughtcrime/securesms/avatar/view/AvatarView.kt index 29e43554d64..020ff88faef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/avatar/view/AvatarView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/avatar/view/AvatarView.kt @@ -71,8 +71,10 @@ class AvatarView @JvmOverloads constructor( /** * Displays Note-to-Self */ - fun displayChatAvatar(recipient: Recipient) { - avatar.setAvatar(recipient) + fun displayChatAvatar(recipient: Recipient, animateAvatar: Boolean = false) { + avatar.buildOptions() + .withAnimateAvatar(animateAvatar) + .load(recipient) } /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java b/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java index b634b55fe83..8da1d6cee32 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java @@ -3,6 +3,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; @@ -224,7 +225,7 @@ private void setAvatar(@NonNull RequestManager requestManager, @Nullable Recipie if (wasUnblurred) { blurred = shouldBlur; request = request.transition(DrawableTransitionOptions.withCrossFade(200)); - } else { + } else if (!avatarOptions.animateAvatar) { request = request.dontAnimate(); } @@ -340,6 +341,9 @@ private final class FixedSizeTarget extends SimpleTarget { @Override public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { setImageDrawable(resource); + if (resource instanceof Animatable) { + ((Animatable) resource).start(); + } } } @@ -349,12 +353,14 @@ public static final class AvatarOptions { private final boolean useSelfProfileAvatar; private final boolean useBlurGradient; private final int fixedSize; + private final boolean animateAvatar; private AvatarOptions(@NonNull Builder builder) { this.quickContactEnabled = builder.quickContactEnabled; this.useSelfProfileAvatar = builder.useSelfProfileAvatar; this.useBlurGradient = builder.useBlurGradient; this.fixedSize = builder.fixedSize; + this.animateAvatar = builder.animateAvatar; } public static final class Builder { @@ -365,6 +371,7 @@ public static final class Builder { private boolean useSelfProfileAvatar = false; private boolean useBlurGradient = false; private int fixedSize = -1; + private boolean animateAvatar = false; private Builder(@NonNull AvatarImageView avatarImageView) { this.avatarImageView = avatarImageView; @@ -390,6 +397,11 @@ private Builder(@NonNull AvatarImageView avatarImageView) { return this; } + public @NonNull Builder withAnimateAvatar(boolean animateAvatar) { + this.animateAvatar = animateAvatar; + return this; + } + public AvatarOptions build() { return new AvatarOptions(this); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt index 2edd3726287..7caba86bd4f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/ConversationSettingsFragment.kt @@ -315,6 +315,7 @@ class ConversationSettingsFragment : .withQuickContactEnabled(false) .withUseSelfProfileAvatar(false) .withFixedSize(ViewUtil.dpToPx(80)) + .withAnimateAvatar(true) .load(state.recipient) if (!state.recipient.isSelf) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/AvatarPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/AvatarPreference.kt index 3ff63e0512d..4ee93cb2d7b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/AvatarPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/AvatarPreference.kt @@ -63,7 +63,7 @@ object AvatarPreference { } avatar.setStoryRingFromState(model.storyViewState) - avatar.displayChatAvatar(model.recipient) + avatar.displayChatAvatar(model.recipient, animateAvatar = true) avatar.disableQuickContact() avatar.setOnClickListener { model.onAvatarClick(avatar) } }