Skip to content

fix(mobile): show transparent avatars without a black background - #9105

Merged
brow merged 1 commit into
mainfrom
jtennant/simone/mobile-webp-thumbnails
Nov 6, 2026
Merged

brow merged 1 commit into
mainfrom
jtennant/simone/mobile-webp-thumbnails

Conversation

@johnmatthewtennant

@johnmatthewtennant johnmatthewtennant commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

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.webp thumbnail that keeps transparency, alongside the {sha}.thumb.jpg that every relay writes. This PR loads the WebP first.

  • MediaImage with preferThumbnail tries .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.
  • BuzzNotificationAvatarLoader follows 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 MediaImage on the same relay, before and after (widget harness on an iOS simulator).

Before After
Before: black square behind the avatar After: transparent corners

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.
  • The relay thumbnail journey tests run against a relay that 404s .thumb.webp, so they cover the older-relay path end to end.
  • BuzzNotificationAvatarLoaderTests checks the WebP-then-JPEG thumbnail order for relay media, and that non-relay media gets no thumbnails.

🤖 Generated with Claude Code

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
johnmatthewtennant marked this pull request as ready for review November 6, 2026 01:30
@johnmatthewtennant
johnmatthewtennant requested a review from a team as a code owner November 6, 2026 01:30
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 6, 2026
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated, security-focused review generated by Codex.
Use it as a supplement to human review; false positives are possible.

Scope

  • Exact PR diff: fbfbf3d64f028da95368f8cd5c80ca0f77e482d0...e669549285e19c43a7c8c756c632eaecb0218a3d
  • Model: gpt-6.1-sol

💡 Click "edited" above to see earlier reviews for this PR.


Review Summary

Overall Risk: NONE

No concrete security, correctness, or reliability findings in the authorized PR range.

Findings

No concrete security, correctness, or reliability findings were identified.

Notes

  • Static review only. Builds and tests were not executed, as requested.

Generated by Codex Security Review |
Requested by: @johnmatthewtennant |
Workflow run

@brow
brow merged commit b894fb0 into main Nov 6, 2026
60 checks passed
@brow
brow deleted the jtennant/simone/mobile-webp-thumbnails branch November 6, 2026 02:33
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

1 inactive deployment
codex-review — e6695492 Deployed Nov 6, 2026 by johnmatthewtennant via Run Codex Security Review #13334
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security-review-current The posted Codex security review matches its recorded range.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants