Repository navigation
fix(mobile): show transparent avatars without a black background - #9105
Merged
Merged
Conversation
Relays now write a `.thumb.webp` thumbnail that keeps transparency beside the `.thumb.jpg` one. Small avatars and notification avatars ask for the WebP first, then the JPEG, then the original, so older relays and images uploaded before the change still render. Co-authored-by: Simone <0828be588d5c9c4d092c5b1cf01761d5aef63d6b104807fd8e8284d517dd1a99@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: John Tennant <[email protected]>
johnmatthewtennant
marked this pull request as ready for review
November 6, 2026 01:30
johnmatthewtennant
temporarily deployed
to
codex-review
November 6, 2026 01:31 — with
GitHub Actions
Inactive
🔐 Codex Security Review
Review SummaryOverall Risk: NONE
FindingsNo concrete security, correctness, or reliability findings were identified. Notes
Generated by Codex Security Review | |
brow
approved these changes
Nov 6, 2026
johnmatthewtennant
added a commit
that referenced
this pull request
Nov 6, 2026
## Summary Clients ask for an image's small `.thumb.webp` thumbnail first and fall back to `.thumb.jpg` on a 404. Images uploaded before [#9003](#9003) only have the JPEG, so every client pays an extra 404 for them and transparent avatars keep showing on a black background. The same thing happens when a thumbnail write failed at upload time. When a thumbnail variant is missing but its image original exists, the relay now regenerates the thumbnails on that request and serves them with 200. It uses the same generator and storage writes as upload, which are now one shared `store_image_thumbnails`. Later requests are ordinary hits. - GET (full and range) and HEAD both regenerate, so a HEAD-then-GET client sees the same result. - Regeneration runs only after the existing tenant, auth and sidecar checks for that thumbnail. - It is bounded. At most two regenerations run per relay process (`try_acquire`, no waiting), and originals larger than `max_image_bytes` are skipped. In both cases, and for non-images, missing originals or any decode or storage error, the response is the 404 it is today. Errors are logged at warn. ### Related issue Follow-up to [#9003](#9003) and [#9105](#9105), which made relays write WebP thumbnails and clients prefer them. ### Testing Two router-level tests against Postgres and MinIO upload a PNG through the real route, then delete its thumbnails: - `missing_thumbnail_is_regenerated_from_image_original`: GET and HEAD of `.thumb.webp` and `.thumb.jpg` return 200 with the right content type, and both objects are stored afterward. With regeneration disabled it fails with `GET webp: 404, expected 200`. - `missing_thumbnail_is_not_regenerated_when_unsafe`: a non-image blob, a missing original, an oversize original and a busy relay (no free permit) each return 404 and store nothing. Once the permits are free, the same request returns 200. Removing the size cap or the permit guard fails it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: John Tennant <[email protected]> Co-authored-by: Simone <0828be588d5c9c4d092c5b1cf01761d5aef63d6b104807fd8e8284d517dd1a99@buzz.block.builderlab.xyz> Co-authored-by: Claude Sonnet 5.5 <[email protected]>
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Transparent PNG and GIF avatars render on a black background in mobile avatars and iOS notification avatars. Both load the relay's small thumbnail, which was always a JPEG with no alpha channel.
block/buzz#9003 makes relays write a
{sha}.thumb.webpthumbnail that keeps transparency, alongside the{sha}.thumb.jpgthat every relay writes. This PR loads the WebP first.MediaImagewithpreferThumbnailtries.thumb.webp, then.thumb.jpg, then the original. Only a 404 moves on to the next source; any other failure still shows the error widget. Missing thumbnails are remembered as before, so later builds skip straight to the source that exists.BuzzNotificationAvatarLoaderfollows the same order for notification avatars.Relays without 9003, and images uploaded before it, keep rendering from the JPEG as they do today.
Screenshots
A transparent PNG avatar rendered by
MediaImageon the same relay, before and after (widget harness on an iOS simulator).Related issue
AIDA-2308 (internal). The desktop counterpart is block/buzz-app#2477.
Testing
missing thumbnails fall back to the JPEG, then the original(avatar_image_test.dart): when the relay 404s every thumbnail, the avatar requests the WebP, then the JPEG, then the original. When the WebP fails with a 500, the avatar shows its fallback and requests neither the JPEG nor the original..thumb.webp, so they cover the older-relay path end to end.BuzzNotificationAvatarLoaderTestschecks the WebP-then-JPEG thumbnail order for relay media, and that non-relay media gets no thumbnails.🤖 Generated with Claude Code