Draw locked covers as artwork instead of a question mark

A reward-gated album showed a bare  over the generated gradient, which reads as
"something is broken" rather than "something is waiting". It is now a proper
placeholder cover, with a separate one for audiobooks and podcasts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-19 18:05:19 +02:00
parent 36e93be79b
commit f3f7082fb8
3 changed files with 10 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
web/public/hiddenalbum.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@@ -26,8 +26,8 @@ interface Props {
style?: CSSProperties;
/** Print the title over generated art. Off for thumbnails, where it would not fit. */
label?: boolean;
/** A reward-gated album/track not yet earned - shows a question mark instead of the
* real art or title, regardless of `has_cover`. */
/** A reward-gated album/track not yet earned - shows a placeholder cover instead of
* the real art or title, regardless of `has_cover`. */
locked?: boolean;
}
@@ -53,20 +53,18 @@ export function Cover({ album, size, fit = "width", radius, className, style, la
}}
>
{locked ? (
<div
<img
src={book ? "/hidden_audiobook_or_podcast.png" : "/hiddenalbum.png"}
alt=""
style={{
position: "absolute",
inset: 0,
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: Math.max(22, Math.round(size / 2.2)),
color: "oklch(99% 0 0 / .85)",
textShadow: "0 2px 8px oklch(15% 0.05 210 / .6)",
width: "100%",
height: "100%",
objectFit: "cover",
clipPath: book ? "inset(0 5% 0 0)" : undefined,
}}
>
</div>
/>
) : (
<>
{!album.has_cover && label && (