import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import LinksSentence from './LinksSentence'; import { dater } from './Dater'; import { nice_number } from './NiceNumber'; import URILink from './URILink'; import ContextMenuTrigger from './ContextMenuTrigger'; import Icon from './Icon'; import Thumbnail from './Thumbnail'; import Popularity from './Popularity'; import Link from './Link'; import { I18n } from '../locale'; import { encodeUri } from '../util/format'; import { scrollTo, sourceIcon } from '../util/helpers'; import * as uiActions from '../services/ui/actions'; import * as lastfmActions from '../services/lastfm/actions'; import * as mopidyActions from '../services/mopidy/actions'; import * as spotifyActions from '../services/spotify/actions'; const getValue = (item = {}, name = '') => { const { [name]: value } = item; switch (name) { case 'tracks': { const { tracks_total: total, } = item; if (!total && !value) return null; return ; } case 'artists': { const { artists_total: total, artists_uris: array, } = item; if (Array.isArray(value)) return ; if (!total && !array) return null; return ; } case 'albums': { const { albums_total: total, albums_uris: array, } = item; if (!total && !array) return null; return ; } case 'source': return ; default: break; } // All options beyond here don't play well with null/undefined if (!value) return null; switch (name) { case 'followers': return ; case 'listeners': return ; case 'added_at': return ; case 'last_modified': return ; case 'owner': return {value.id}; case 'popularity': return ; default: break; } if (value === true) return ; if (typeof (value) === 'number') return {value.toLocaleString()}; return value; }; const ListItem = ({ item, middle_column, right_column, details, thumbnail, nocontext, getLink, }) => { if (!item) return null; const dispatch = useDispatch(); const spotify_available = useSelector((state) => state.spotify.access_token); const history = useHistory(); // Load images useEffect(() => { if (!item.images) { switch (item.type) { case 'artist': if (spotify_available) { dispatch(spotifyActions.getArtistImages(item)); } break; case 'album': dispatch(mopidyActions.getImages([item.uri])); break; default: break; } } }, [item.images]); const onContextMenu = (e) => { e.preventDefault(); dispatch( uiActions.showContextMenu({ e, context: item.type, uris: [item.uri], items: [item], tracklist_uri: item.uri, // not needed? }), ); }; /** * Handled as a click, rather than an object so we can direct to a link, UNLESS we have clicked * on a sub-link (we may have nested links to Albums for example). HTML does not allow nested * tags. * * @param {Object} e */ const onClick = (e) => { let to = ''; if (getLink) { to = getLink(item); } else if (item.link) { to = item.link; } else { to = `/${item.type}/${encodeUri(item.uri)}`; } if (e.target.tagName.toLowerCase() !== 'a') { e.preventDefault(); history.push(to); scrollTo(); } } let className = 'list__item'; if (item.type) className += ` list__item--${item.type}`; if (item.loading) className += ' list__item--loading'; if (middle_column) className += ' list__item--has-middle-column'; if (thumbnail) className += ' list__item--has-thumbnail'; if (details) className += ' list__item--has-details'; return (
{ right_column && !nocontext && (
{ right_column.map((column) => ( {getValue(item, column)} )) } {!nocontext && ( )}
) }
{thumbnail && ( )}
{ item.name !== undefined ? getValue(item, 'name') : {item.uri} }
{details ? (
    { details.map((detail) => { const value = getValue(item, detail); if (!value) return null; return (
  • {value}
  • ); }) }
) : null}
{middle_column && (
{ middle_column.map((column) => ( {getValue(item, column)} )) }
)}
); }; export { ListItem, }; export default { ListItem, };