mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-29 22:47:48 +01:00
Route the album grid, CoverArtAvatar (artist/playlist lists) and the radio list's cover field through CoverImage instead of each carrying its own useImageUrl + blurhash-overlay wiring. CoverImage gains a default object-fit: cover. Radio keeps its uploaded-image gate and the generic radio placeholder for stations with no art.
64 lines
1.9 KiB
JavaScript
64 lines
1.9 KiB
JavaScript
import PropTypes from 'prop-types'
|
|
import clsx from 'clsx'
|
|
import { makeStyles } from '@material-ui/core/styles'
|
|
import config from '../config'
|
|
import subsonic from '../subsonic'
|
|
import { useImageUrl } from './useImageUrl'
|
|
import { BlurHashCanvas } from './BlurHashCanvas'
|
|
|
|
const useStyles = makeStyles({
|
|
root: { position: 'relative', display: 'inline-flex' },
|
|
blur: { position: 'absolute', top: 0, left: 0, zIndex: 0 },
|
|
img: { position: 'relative', zIndex: 1 },
|
|
})
|
|
|
|
// CoverImage renders an entity's cover through the shared useImageUrl blob cache, so it survives
|
|
// React remounts without re-fetching, with the blurhash as the loading placeholder. `className`
|
|
// supplies the size (and any transition); the fade opacity is applied here.
|
|
export const CoverImage = ({
|
|
record,
|
|
size = config.uiCoverArtSize,
|
|
square = false,
|
|
className,
|
|
title,
|
|
onClick,
|
|
}) => {
|
|
const classes = useStyles()
|
|
const url = record ? subsonic.getCoverArtUrl(record, size, square) : ''
|
|
const { imgUrl, loading } = useImageUrl(url)
|
|
if (!record) return null
|
|
|
|
const showBlurHash = loading && record.blurHash
|
|
const handleClick = imgUrl && onClick ? onClick : undefined
|
|
return (
|
|
<div className={classes.root}>
|
|
{showBlurHash && (
|
|
<BlurHashCanvas
|
|
hash={record.blurHash}
|
|
className={clsx(className, classes.blur)}
|
|
/>
|
|
)}
|
|
<img
|
|
src={imgUrl || undefined}
|
|
alt={title}
|
|
title={title}
|
|
onClick={handleClick}
|
|
className={clsx(className, showBlurHash && classes.img)}
|
|
style={{
|
|
objectFit: 'cover',
|
|
opacity: loading ? 0.5 : 1,
|
|
cursor: handleClick ? 'pointer' : 'default',
|
|
}}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
CoverImage.propTypes = {
|
|
record: PropTypes.object,
|
|
size: PropTypes.number,
|
|
square: PropTypes.bool,
|
|
className: PropTypes.string,
|
|
title: PropTypes.string,
|
|
onClick: PropTypes.func,
|
|
}
|