fix(slideshow): stop "no crop" fit letterboxing a pre-cropped frame (stable) (#1015) (#1019)

Backport of #1018 to the curated channel; the reporter on #1015 is running v3.45.14.

The slideshow resolved its image as preview_url || hero_url || url. preview_url is only emitted when lightbox_preview_enabled is on (default false), so a default install fell through to hero_url — the 1920x1080 fit:'cover' centre crop built for gallery header banners. object-fit: contain then letterboxed an already-cropped 16:9 frame.

Emits slideshow_url (same aspect-preserved preview tier) unconditionally for image photos; the show prefers it and never falls back to hero_url. preview_url stays gated so the lightbox opt-in is unchanged.
This commit is contained in:
Paul Nothaft
2026-08-10 13:32:24 +02:00
committed by GitHub
parent cee0a380a6
commit 2bdb1204fe
4 changed files with 174 additions and 1 deletions
+11
View File
@@ -726,6 +726,17 @@ router.get('/:slug/photos', verifyGalleryAccess, resolveGuest, async (req, res)
&& (!photo.mime_type || !photo.mime_type.startsWith('video/'))
? `/api/gallery/${req.params.slug}/preview/${photo.id}${wmQuery}`
: null,
// Slideshow source (#1015). Same preview tier, but emitted
// unconditionally: the slideshow has no `url` fallback worth
// taking (originals are projector-sized) and must never land on
// `hero_url`, which is cover-cropped to 16:9 — that made the
// "no crop" fit letterbox an already-cropped frame. The preview
// route generates lazily and redirects to the original on any
// failure, so this is safe even where no preview exists yet.
slideshow_url: photo.media_type !== 'video'
&& (!photo.mime_type || !photo.mime_type.startsWith('video/'))
? `/api/gallery/${req.params.slug}/preview/${photo.id}${wmQuery}`
: null,
secure_url_template: `/api/secure-images/${req.params.slug}/secure/${photo.id}/{{token}}`,
download_url_template: `/api/secure-images/${req.params.slug}/secure-download/${photo.id}/{{token}}`,
type: photo.type,