From ce2954cf2b1e55b98275377a4b16dab0e65d0e6d Mon Sep 17 00:00:00 2001 From: npeter83 Date: Wed, 19 Aug 2026 02:00:24 +0200 Subject: [PATCH] fix(downloads): carry the active account on the Library poster URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An can't send the X-Siftlode-Account header, so the poster.jpg request resolved to the session-default account and _accessible_job 404'd it for any download owned by a different (per-tab) account — every card then fell back to the source's remote thumbnail, which for Facebook is an expiring fbcdn URL, so the Library showed blank thumbnails in a multi-account session. The 0.69.1 local-poster-primary change made this the primary image, exposing it broadly. Append ?account= to the poster URL via a new api.posterImageUrl(), the same wallet-gated header-less selection downloadFileUrl / storyboardImageUrl already use (resolved_user_id reads ?account= for exactly these contexts). --- frontend/src/components/DownloadCenter.tsx | 7 ++++++- frontend/src/lib/api/downloads.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/DownloadCenter.tsx b/frontend/src/components/DownloadCenter.tsx index 9facb718..8f3c6b14 100644 --- a/frontend/src/components/DownloadCenter.tsx +++ b/frontend/src/components/DownloadCenter.tsx @@ -89,7 +89,12 @@ function Thumb({ job }: { job: DownloadJob }) { // rule on the source domain can't break it. The source's remote thumbnail_url is only a fallback for // the rare poster-less asset (a thumbnail-less source whose ffmpeg frame-cut also failed). const remote = job.asset?.thumbnail_url ?? null; - const primary = job.poster_url || remote; + // `job.poster_url` only SIGNALS a poster exists; the actual src must carry ?account= (see + // api.posterImageUrl). A plain can't send the X-Siftlode-Account header, so without it the + // poster resolves to the session-default account and 404s for a per-tab account's download — which, + // now that the poster is the primary image, reads as a blank Library thumbnail. + const poster = job.poster_url ? api.posterImageUrl(job.id) : null; + const primary = poster || remote; // On load failure (a genuinely missing poster file) fall back to the remote source thumbnail. const [src, setSrc] = useState(primary); useEffect(() => setSrc(primary), [primary]); diff --git a/frontend/src/lib/api/downloads.ts b/frontend/src/lib/api/downloads.ts index 296f6ca3..25dbf7c9 100644 --- a/frontend/src/lib/api/downloads.ts +++ b/frontend/src/lib/api/downloads.ts @@ -225,6 +225,15 @@ export const downloadsApi = { ? `/api/downloads/${id}/storyboard.jpg?account=${a}` : `/api/downloads/${id}/storyboard.jpg`; }, + // The locally-generated poster (an src → direct nav, so same ?account= wallet gate). Without + // it the poster resolves to the session-default account and 404s for a per-tab account's download — + // which reads as a blank Library thumbnail once the poster is the card's primary image. + posterImageUrl: (id: number): string => { + const a = getActiveAccount(); + return a != null + ? `/api/downloads/${id}/poster.jpg?account=${a}` + : `/api/downloads/${id}/poster.jpg`; + }, // admin adminDownloads: (): Promise => req("/api/admin/downloads"),