a video in a carousel gets its poster, not a 404

A video has no width rungs — poster-448.webp and friends are cut from a still —
so asking for 320.webp returns a 404 and the grid drew a broken tile with no clue
why. Every grid in the panel was doing it, and a carousel is explicitly allowed
to hold both kinds.

posterUrl already existed for this and nothing called it. mediaThumbUrl decides
from the extension so a screen showing mixed media does not have to know the
difference.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-05 14:32:52 +01:00
co-authored by Claude Opus 5
parent b7455c0470
commit 55be0a1860
3 changed files with 21 additions and 4 deletions
+17
View File
@@ -48,3 +48,20 @@ export const originalUrl = (path: string, width: number): string => {
const encoded = path.split('/').map(encodeURIComponent).join('/');
return `/api/fofos-admin/original/${encoded}?width=${Math.round(width)}&token=${encodeURIComponent(token)}`;
};
/** Extensions av-club treats as video. The same list the site's own `kindFor` uses. */
const VIDEO = /\.(mp4|mov|webm|m4v|avi|mkv)$/i;
/**
* A thumbnail for anything in the media store, picture or video.
*
* A video has no width rungs — `poster-448.webp` and friends are cut from a still, and asking for
* `320.webp` gets a 404 and a broken image. Every grid in this panel was doing exactly that, so a
* carousel holding a video showed a broken tile with no clue why.
*
* `posterUrl` already existed for this and nothing called it. One helper that decides from the
* extension, so a screen showing mixed media does not have to know the difference — which is the
* whole point, since a carousel is explicitly allowed to hold both.
*/
export const mediaThumbUrl = (path: string, width: 256 | 320 | 480 | 640 | 960 | 1280 = 320): string =>
VIDEO.test(path) ? posterUrl(path) : thumbUrl(path, width);