import React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { Route, Switch } from 'react-router-dom'; import ErrorMessage from '../components/ErrorMessage'; import Link from '../components/Link'; import TrackList from '../components/TrackList'; import AlbumGrid from '../components/AlbumGrid'; import Thumbnail from '../components/Thumbnail'; import Parallax from '../components/Parallax'; import ArtistGrid from '../components/ArtistGrid'; import RelatedArtists from '../components/RelatedArtists'; import FollowButton from '../components/Fields/FollowButton'; import ContextMenuTrigger from '../components/ContextMenuTrigger'; import DropdownField from '../components/Fields/DropdownField'; import Icon from '../components/Icon'; import Loader from '../components/Loader'; import * as coreActions from '../services/core/actions'; import * as uiActions from '../services/ui/actions'; import * as mopidyActions from '../services/mopidy/actions'; import { uriSource, sourceIcon, titleCase, } from '../util/helpers'; import { collate } from '../util/format'; import { sortItems, applyFilter, arrayOf } from '../util/arrays'; import { i18n, I18n } from '../locale'; import Button from '../components/Button'; import { trackEvent } from '../components/Trackable'; import { makeItemSelector, makeLoadingSelector, } from '../util/selectors'; class Artist extends React.Component { componentDidMount() { const { uri, coreActions: { loadItem, }, } = this.props; this.setWindowTitle(); loadItem(uri, { full: true }); } componentDidUpdate = ({ uri: prevUri, artist: prevArtist, }) => { const { uri, artist, coreActions: { loadItem, }, } = this.props; if (uri !== prevUri) { loadItem(uri, { full: true }); } if (!prevArtist && artist) this.setWindowTitle(artist); if (prevUri !== uri && artist) this.setWindowTitle(artist); } onResetFilters = () => { this.onChangeFilter(null); this.onChangeSort(null); trackEvent({ category: 'Artist', action: 'FilterAlbums', label: 'Reset' }); } onChangeFilter = (value) => { const { uiActions: { set, hideContextMenu } } = this.props; set({ artist_albums_filter: value }); hideContextMenu(); trackEvent({ category: 'Artist', action: 'FilterAlbums', label: value }); } onChangeSort = (value) => { const { sort, sort_reverse, uiActions: { set, hideContextMenu, }, } = this.props; let reverse = false; if (value !== null && sort === value) { reverse = !sort_reverse; } set({ artist_albums_sort_reverse: reverse, artist_albums_sort: value, }); hideContextMenu(); trackEvent({ category: 'Artist', action: 'SortAlbums', label: `${value} ${reverse ? 'DESC' : 'ASC'}` }); } onPlay = () => { const { artist: { uri, tracks, albums_uris, }, mopidyActions: { playURIs, }, } = this.props; playURIs(arrayOf('uri', tracks) || albums_uris, uri); } setWindowTitle = (artist = this.props.artist) => { const { uiActions: { setWindowTitle } } = this.props; if (artist) { setWindowTitle(i18n('artist.title_window', { name: artist.name })); } else { setWindowTitle(i18n('artist.title')); } } handleContextMenu = (e) => { const { artist, uri, uiActions: { showContextMenu }, } = this.props; showContextMenu({ e, context: 'artist', items: [artist], uris: [uri], }); } inLibrary = () => { const { uri } = this.props; const libraryName = `${uriSource(uri)}_library_artists`; const { [libraryName]: { items_uris } } = this.props; return items_uris.indexOf(uri) > -1; } renderOverview = () => { const { uri, uiActions, artist, sort, sort_reverse, filter, } = this.props; let { tracks, related_artists, } = artist; let { albums } = this.props; if (sort && albums) { albums = sortItems(albums, sort, sort_reverse); } if (filter && albums) { albums = applyFilter('type', filter, albums); } const sort_options = [ { value: null, label: i18n('artist.albums.sort.default'), }, { value: 'name', label: i18n('artist.albums.sort.name'), }, { value: 'release_date', label: i18n('artist.albums.sort.release_date'), }, { value: 'tracks_uris.length', label: i18n('artist.albums.sort.track_count'), }, ]; const filter_options = [ { value: null, label: i18n('artist.albums.filter.all'), }, { value: 'album', label: i18n('artist.albums.filter.albums'), }, { value: 'single', label: i18n('artist.albums.filter.singles'), }, ]; return (
0 ? '70' : '100'}`}> {tracks &&

}
{related_artists && related_artists.length > 0 && (

)}

{(sort || filter) && ( )}

); } renderTracks = () => { const { artist: { uri, tracks } } = this.props; return (
); } renderRelatedArtists = () => { const { artist } = this.props; return (
); } renderAbout = () => { const { artist: artistProp, artists, } = this.props; const artist = collate( artistProp, { artists, }, ); const thumbnails = artist.images && Array.isArray(artist.images) && artist.images.map( (image) => { if (!image.huge) return null; return (
); } ); return (
{thumbnails}
{artist.followers && (
)} {artist.popularity && (
)} {artist.listeners && (
)}

{artist.biography && (

{artist.biography}


)}
); } render = () => { const { uri, loading, artist, history, } = this.props; if (loading) { return ; } else if (!artist) { return (

); } const scheme = uriSource(uri); const image = (artist.images && artist.images.length) ? artist.images[0].huge : null; const is_spotify = (scheme === 'spotify'); return (

{artist && artist.name}

{is_spotify && ( )}

{artist.tracks && artist.tracks.length > 10 && (

)} {artist.related_artists && (

)}

{this.renderRelatedArtists()} {this.renderTracks()} {this.renderAbout()} {this.renderOverview()}
); } } const mapStateToProps = (state, ownProps) => { const uri = decodeURIComponent(ownProps.match.params.uri); const loadingSelector = makeLoadingSelector([`(.*)${uri}(.*)`]); const artistSelector = makeItemSelector(uri); const artist = artistSelector(state); let albums = null; if (artist && artist.albums_uris) { const albumsSelector = makeItemSelector(artist.albums_uris); albums = albumsSelector(state); } return { uri, artist, albums, loading: loadingSelector(state), theme: state.ui.theme, slim_mode: state.ui.slim_mode, filter: (state.ui.artist_albums_filter ? state.ui.artist_albums_filter : null), sort: (state.ui.artist_albums_sort ? state.ui.artist_albums_sort : null), sort_reverse: (!!state.ui.artist_albums_sort_reverse), spotify_authorized: state.spotify.authorization, }; }; const mapDispatchToProps = (dispatch) => ({ coreActions: bindActionCreators(coreActions, dispatch), uiActions: bindActionCreators(uiActions, dispatch), mopidyActions: bindActionCreators(mopidyActions, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(Artist);