feat(image): add a 1024px size=medium preview tier #174

Merged
cameron merged 1 commits from feat/medium-preview-tier into master 2026-10-16 20:22:55 +00:00
Owner

Adds GET /image?size=medium, a preview capped at 1024px on the long side. Grid and memories tiles used to request size=large (2048px) for tiles shown at about 590px (two columns) to 1180px (one full-width column) on a 3× phone, so they downloaded 10–15× the pixels they displayed. 1024px looks sharp at both sizes and is a quarter of large's pixels.

  • New PhotoSize::Medium and PreviewTier::Medium. Medium previews are cached under _medium/, in the same layout as the other sizes (hash-keyed path first, then the older path-based one).
  • The large and xlarge generators were identical except for the size cap. They're now one function, thumbnails::generate_preview(src, dest, max_dim), so medium didn't need a third copy.
  • Videos fall back to the thumbnail, as they already did for large and xlarge.
  • CLAUDE.md lists the sizes.

Tests:

  • A panorama comes out at 1024×273 for medium and 2048×546 for large.
  • size=medium is accepted as a query parameter.
  • All other tests pass; clippy is clean.
  • Checked on the e2e server: _medium/ gets created, and the app's Memories screen loads medium tiles with the thumbnail shown first.

Pairs with FVR's feat/medium-previews. Deploy this first: older servers reject size=medium.

🤖 Generated with Claude Code

Adds `GET /image?size=medium`, a preview capped at 1024px on the long side. Grid and memories tiles used to request `size=large` (2048px) for tiles shown at about 590px (two columns) to 1180px (one full-width column) on a 3× phone, so they downloaded 10–15× the pixels they displayed. 1024px looks sharp at both sizes and is a quarter of `large`'s pixels. - New `PhotoSize::Medium` and `PreviewTier::Medium`. Medium previews are cached under `_medium/`, in the same layout as the other sizes (hash-keyed path first, then the older path-based one). - The large and xlarge generators were identical except for the size cap. They're now one function, `thumbnails::generate_preview(src, dest, max_dim)`, so medium didn't need a third copy. - Videos fall back to the thumbnail, as they already did for large and xlarge. - CLAUDE.md lists the sizes. Tests: - A panorama comes out at 1024×273 for medium and 2048×546 for large. - `size=medium` is accepted as a query parameter. - All other tests pass; clippy is clean. - Checked on the e2e server: `_medium/` gets created, and the app's Memories screen loads medium tiles with the thumbnail shown first. Pairs with FVR's `feat/medium-previews`. **Deploy this first**: older servers reject `size=medium`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cameron added 1 commit 2026-10-16 20:07:41 +00:00
Grid and memories tiles requested `size=large` (up to 2048px) for tiles
that display at ~590px (two columns) to ~1180px (one full-width column)
on a 3× phone, downloading 10–15× the pixels they show. `medium` caps
the long edge at 1024: crisp at both, a quarter of `large`'s pixels.
Cached under `_medium/` like the other tiers.

The large and xlarge generators were copies differing only in their
cap; fold them into one `generate_preview(src, dest, max_dim)` so the
third tier doesn't make a third copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cameron merged commit f1779358b5 into master 2026-10-16 20:22:55 +00:00
cameron deleted branch feat/medium-preview-tier 2026-10-16 20:22:55 +00:00
Sign in to join this conversation.