fix(album): hide Artist Bio button on Various-Artists compilations (#733)

* fix(album): hide Artist Bio button on Various-Artists compilations

The Album header showed an Artist Bio button on every album, but
when the album artist label is "Various Artists" / "Various" / "VA"
or a language equivalent there is no single artist to fetch a bio
for — the button opened an empty modal. Hide both the mobile icon
and the desktop button when the label matches that heuristic.

* docs(changelog): album bio button hidden for compilations (PR #733)
This commit is contained in:
Frank Stellmacher
2026-05-16 03:01:12 +02:00
committed by GitHub
parent 58d3bcd695
commit 7f9b5bd57d
2 changed files with 38 additions and 11 deletions
+6
View File
@@ -559,6 +559,12 @@ Foundational work: faster reviews, narrower diffs, and a safety net under the pa
* The Info tab rendered one frame on each track switch with the previous track's artist image URL paired with the new track's cache key — **`CachedImage`**'s IndexedDB then persisted that mismatched blob, so every subsequent track stayed stuck on the previous artist's image. Artist info and song detail are now held as **`{ id, info }`** tuples and the image render is gated on id-match, so source and cache key always come from the same track. * The Info tab rendered one frame on each track switch with the previous track's artist image URL paired with the new track's cache key — **`CachedImage`**'s IndexedDB then persisted that mismatched blob, so every subsequent track stayed stuck on the previous artist's image. Artist info and song detail are now held as **`{ id, info }`** tuples and the image render is gated on id-match, so source and cache key always come from the same track.
### Album header — Artist Bio button hidden on Various-Artists compilations
**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#733](https://github.com/Psychotoxical/psysonic/pull/733)**
* The Album header showed an **Artist Bio** button on every album, but when the album-artist label is **"Various Artists"**, **"Various"**, **"VA"** or a language equivalent there is no single artist to fetch a bio for and the button opened an empty modal. Both the mobile icon and the desktop button are now hidden when the album-artist label matches that compilation heuristic.
## [1.45.0] - 2026-05-04 ## [1.45.0] - 2026-05-04
## Added ## Added
+32 -11
View File
@@ -17,6 +17,22 @@ import { formatMb } from '../utils/format/formatBytes';
import { sanitizeHtml } from '../utils/sanitizeHtml'; import { sanitizeHtml } from '../utils/sanitizeHtml';
import { OpenArtistRefInline } from './OpenArtistRefInline'; import { OpenArtistRefInline } from './OpenArtistRefInline';
/** True when the album artist label means "no single artist" — `getArtistInfo`
* has nothing meaningful to return for these, so the Artist Bio entry is hidden.
*/
function isVariousArtistsLabel(name: string | undefined | null): boolean {
if (!name) return false;
const trimmed = name.trim().toLowerCase();
return (
trimmed === 'various artists' ||
trimmed === 'various' ||
trimmed === 'va' ||
trimmed === 'multiple artists' ||
trimmed === 'verschiedene interpreten' ||
trimmed === 'verschiedene'
);
}
function BioModal({ bio, onClose }: { bio: string; onClose: () => void }) { function BioModal({ bio, onClose }: { bio: string; onClose: () => void }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
@@ -108,6 +124,7 @@ export default function AlbumHeader({
const totalSize = songs.reduce((acc, s) => acc + (s.size ?? 0), 0); const totalSize = songs.reduce((acc, s) => acc + (s.size ?? 0), 0);
const formatLabel = [...new Set(songs.map(s => s.suffix).filter((f): f is string => !!f))].map(f => f.toUpperCase()).join(' / '); const formatLabel = [...new Set(songs.map(s => s.suffix).filter((f): f is string => !!f))].map(f => f.toUpperCase()).join(' / ');
const isNewAlbum = isAlbumRecentlyAdded(info.created); const isNewAlbum = isAlbumRecentlyAdded(info.created);
const showBioButton = !isVariousArtistsLabel(info.artist);
const lightboxCoverSrc = useMemo( const lightboxCoverSrc = useMemo(
() => (info.coverArt ? buildCoverArtUrl(info.coverArt, 2000) : ''), () => (info.coverArt ? buildCoverArtUrl(info.coverArt, 2000) : ''),
@@ -248,14 +265,16 @@ export default function AlbumHeader({
<Share2 size={16} /> <Share2 size={16} />
</button> </button>
<button {showBioButton && (
className="album-icon-btn album-icon-btn--sm" <button
onClick={onBio} className="album-icon-btn album-icon-btn--sm"
aria-label={t('albumDetail.artistBio')} onClick={onBio}
data-tooltip={t('albumDetail.artistBio')} aria-label={t('albumDetail.artistBio')}
> data-tooltip={t('albumDetail.artistBio')}
<Highlighter size={16} /> >
</button> <Highlighter size={16} />
</button>
)}
{downloadProgress !== null ? ( {downloadProgress !== null ? (
<div className="album-icon-btn album-icon-btn--sm album-icon-btn--progress"> <div className="album-icon-btn album-icon-btn--sm album-icon-btn--progress">
@@ -338,9 +357,11 @@ export default function AlbumHeader({
</button> </button>
</div> </div>
<button className="btn btn-ghost" id="album-bio-btn" onClick={onBio}> {showBioButton && (
<Highlighter size={16} /> {t('albumDetail.artistBio')} <button className="btn btn-ghost" id="album-bio-btn" onClick={onBio}>
</button> <Highlighter size={16} /> {t('albumDetail.artistBio')}
</button>
)}
{downloadProgress !== null ? ( {downloadProgress !== null ? (
<div className="download-progress-wrap"> <div className="download-progress-wrap">