Skip to content

Play animated GIF avatars in the contact/group detail header and fullscreen preview - #14913

Open
br4yd wants to merge 3 commits into
signalapp:mainfrom
br4yd:feature/animated-avatar-preview
Open

Play animated GIF avatars in the contact/group detail header and fullscreen preview#14913
br4yd wants to merge 3 commits into
signalapp:mainfrom
br4yd:feature/animated-avatar-preview

Conversation

@br4yd

@br4yd br4yd commented Aug 4, 2026

Copy link
Copy Markdown

Contributor checklist

  • I am following the Code Style Guidelines
  • I have tested my contribution on these devices:
    • Samsung Galaxy S26 Ultra, Android 17
    • Google Pixel 10 Pro, Android 17
  • My contribution is fully baked and ready to be merged as is
  • I ensure that all the open issues my contribution fixes are mentioned in the commit message of my first commit using the Fixes #1234 syntax
    (no tracked issue for this — not filed as a bug, just noticed the behavior)

Description

Signal Desktop renders avatars as a plain <img>/CSS background-image, so an animated GIF avatar (e.g. a phone's system contact photo synced to a linked device, or an animated Signal profile photo) plays natively via Chromium. On Android, every avatar is frozen to its first frame regardless of source format, because AvatarImageView.setAvatar() unconditionally calls Glide's .dontAnimate().

Animating every avatar everywhere needs system resources. GIFs decode and redraw every frame, which is real cost in a scrolling list with dozens of recycled avatar views on screen at once. So instead of removing dontAnimate() globally, this adds an opt-in AvatarOptions.animateAvatar flag (default false, so every existing call site keeps today's behavior unchanged) and only turns it on in the two places where exactly one avatar is ever shown at a time:

  • The large avatar in the conversation-settings / recipient & group details header (ConversationSettingsFragment).
  • The dedicated fullscreen avatar viewer (AvatarPreviewActivity), which previously always requested .asBitmap(). It has been sitched to a plain Drawable request so an animated GifDrawable can be returned there at all.

Chat list rows, contact lists, group member lists, call log, etc. are untouched. They keep dontAnimate() to save system resources and keep performance.

Known limitation: this only helps animated GIF avatars. Signal Android's Glide setup (SignalGlideComponents) registers a decoder for InputStream -> GifDrawable, but has no equivalent for animated WebP. An animated-WebP avatar would still render as static after this change.
Adding that would mean registering a separate animated-WebP decoder in the Glide pipeline, which felt like a bigger, separate change for me and is IMO out of scope here.

Testing

Tested on a real device with a contact whose avatar is an animated GIF: it now plays in both the conversation-settings header and the fullscreen preview, while chat-list/contact-list rows remain static as intended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant