import { useEffect, useState } from 'react' import { Card, CardContent, CardMedia, Collapse, makeStyles, Typography, useMediaQuery, withWidth, } from '@material-ui/core' import { ArrayField, ChipField, Link, SingleFieldList, useRecordContext, useTranslate, } from 'react-admin' import Lightbox from 'react-image-lightbox' import config from '../config' import 'react-image-lightbox/style.css' import subsonic from '../subsonic' import { ArtistLinkField, CollapsibleComment, DurationField, formatRange, LoveButton, RatingField, SizeField, useAlbumsPerPage, useImageLoadingState, } from '../common' import { formatFullDate, intersperse } from '../utils' import AlbumExternalLinks from './AlbumExternalLinks' import { SafeHTML } from '../common/SafeHTML' const useStyles = makeStyles( (theme) => ({ root: { [theme.breakpoints.down('xs')]: { padding: '0.7em', minWidth: '20em', }, [theme.breakpoints.up('sm')]: { padding: '1em', minWidth: '32em', }, }, cardContents: { display: 'flex', }, details: { display: 'flex', flexDirection: 'column', }, content: { flex: '2 0 auto', }, coverParent: { [theme.breakpoints.down('xs')]: { height: '8em', width: '8em', minWidth: '8em', }, [theme.breakpoints.up('sm')]: { height: '10em', width: '10em', minWidth: '10em', }, [theme.breakpoints.up('lg')]: { height: '15em', width: '15em', minWidth: '15em', }, backgroundColor: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', }, cover: { objectFit: 'contain', cursor: 'pointer', display: 'block', width: '100%', height: '100%', backgroundColor: 'transparent', transition: 'opacity 0.3s ease-in-out', }, coverLoading: { opacity: 0.5, }, loveButton: { top: theme.spacing(-0.2), left: theme.spacing(0.5), }, notes: { display: 'inline-block', marginTop: '1em', float: 'left', wordBreak: 'break-word', cursor: 'pointer', }, recordName: {}, recordArtist: {}, recordMeta: {}, genreList: { marginTop: theme.spacing(0.5), }, externalLinks: { marginTop: theme.spacing(1.5), }, }), { name: 'NDAlbumDetails', }, ) const useGetHandleGenreClick = (width) => { const [perPage] = useAlbumsPerPage(width) return (id) => { return `/album?filter={"genre_id":["${id}"]}&order=ASC&sort=name&perPage=${perPage}` } } const GenreChipField = withWidth()(({ width, ...rest }) => { const record = useRecordContext(rest) const genreLink = useGetHandleGenreClick(width) return ( e.stopPropagation()}> {}} /> ) }) const GenreList = () => { const classes = useStyles() return ( ) } export const Details = (props) => { const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const translate = useTranslate() const record = useRecordContext(props) // Create an array of detail elements let details = [] const addDetail = (obj) => { const id = details.length details.push({obj}) } // Calculate date related fields const yearRange = formatRange(record, 'year') const date = record.date ? formatFullDate(record.date) : yearRange const originalDate = record.originalDate ? formatFullDate(record.originalDate) : formatRange(record, 'originalYear') const releaseDate = record?.releaseDate && formatFullDate(record.releaseDate) const dateToUse = originalDate || date const isOriginalDate = originalDate && dateToUse !== date const showDate = dateToUse && dateToUse !== releaseDate // Get label for the main date display const getDateLabel = () => { if (isXsmall) return '♫' if (isOriginalDate) return translate('resources.album.fields.originalDate') return null } // Get label for release date display const getReleaseDateLabel = () => { if (!isXsmall) return translate('resources.album.fields.releaseDate') if (showDate) return '○' return null } // Display dates with appropriate labels if (showDate) { addDetail(<>{[getDateLabel(), dateToUse].filter(Boolean).join(' ')}) } if (releaseDate) { addDetail( <>{[getReleaseDateLabel(), releaseDate].filter(Boolean).join(' ')}, ) } addDetail( <> {record.songCount + ' ' + translate('resources.song.name', { smart_count: record.songCount, })} , ) !isXsmall && addDetail() !isXsmall && addDetail() // Return the details rendered with separators return <>{intersperse(details, ' · ')} } const AlbumDetails = (props) => { const record = useRecordContext(props) const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('lg')) const classes = useStyles() const [expanded, setExpanded] = useState(false) const [albumInfo, setAlbumInfo] = useState() const { imageLoading, imageError, isLightboxOpen, handleImageLoad, handleImageError, handleOpenLightbox, handleCloseLightbox, } = useImageLoadingState(record.id) let notes = albumInfo?.notes || record.notes if (notes) { notes += '..' } useEffect(() => { subsonic .getAlbumInfo(record.id) .then((resp) => resp.json['subsonic-response']) .then((data) => { if (data.status === 'ok') { setAlbumInfo(data.albumInfo) } }) .catch((e) => { // eslint-disable-next-line no-console console.error('error on album page', e) }) }, [record]) const imageUrl = subsonic.getCoverArtUrl(record, config.uiCoverArtSize) const fullImageUrl = subsonic.getCoverArtUrl(record) return (
{record.name} {record?.tags?.['albumversion']}
{config.enableStarRating && (
)} {isDesktop ? ( ) : ( {record.genre} )} {!isXsmall && ( {config.enableExternalServices && ( )} )} {isDesktop && notes && ( setExpanded(!expanded)} > {notes} )} {isDesktop && record['comment'] && ( )}
{!isDesktop && record['comment'] && ( )} {!isDesktop && notes && (
setExpanded(!expanded)} > {notes}
)} {isLightboxOpen && !imageError && ( )}
) } export default AlbumDetails