fix(download): sibling cover via curl + episode image fallback

The download wrote its sibling .jpg with Bun fetch — which hangs in
compiled binaries, so shipped builds never produced offline cover art.
Now curl (same flags as the cover cache). Also falls back to the
episode's own image when the feed has no channel cover (URL-added
feeds like The Fifth Column). mpv --cover-art-auto=exact picks up the
same-basename .jpg (verified against mpv 0.41).
This commit is contained in:
2026-08-12 10:59:06 -04:00
parent 13664c3cec
commit b5432e3e5f

View File

@@ -237,23 +237,36 @@ function createDownloadStore() {
}); });
// Write the podcast cover beside the audio so mpv's // Write the podcast cover beside the audio so mpv's
// --cover-art-auto=exact picks it up for Now Playing art. // --cover-art-auto=exact picks it up for Now Playing art when the
const coverUrl = useFeedStore() // local file plays (same basename, .jpg extension — verified
// against mpv 0.41). curl, NOT fetch: Bun's fetch hangs in
// compiled binaries, so the shipped app never wrote this file.
// Falls back to the episode's own image when the feed has no
// channel cover (URL-added feeds).
const feedStore = useFeedStore();
const episode = feedStore.findEpisode(item.episodeId);
const coverUrl =
feedStore
.feeds() .feeds()
.find((f) => f.id === item.feedId)?.podcast.coverUrl; .find((f) => f.id === item.feedId)?.podcast.coverUrl ??
episode?.imageUrl;
if (coverUrl && result.filePath) { if (coverUrl && result.filePath) {
const dot = result.filePath.lastIndexOf("."); const dot = result.filePath.lastIndexOf(".");
if (dot > 0) { if (dot > 0) {
const coverPath = result.filePath.slice(0, dot) + ".jpg"; const coverPath = result.filePath.slice(0, dot) + ".jpg";
fetch(coverUrl) Bun.spawn([
.then(async (r) => { "curl",
if (!r.ok) return; "-sS",
await Bun.write( "--fail",
"-m",
"8",
"--max-filesize",
"2097152",
"-o",
coverPath, coverPath,
new Uint8Array(await r.arrayBuffer()), coverUrl,
); ])
}) .exited.catch(() => {});
.catch(() => {});
} }
} }
} else { } else {