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 LazyLoadListener from '../components/LazyLoadListener'; 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 * as pusherActions from '../services/pusher/actions'; import * as lastfmActions from '../services/lastfm/actions'; import * as spotifyActions from '../services/spotify/actions'; import { uriSource, getFromUri, isLoading, sourceIcon, titleCase, } from '../util/helpers'; import { collate } from '../util/format'; import { sortItems, applyFilter } from '../util/arrays'; import { i18n, I18n } from '../locale'; import Button from '../components/Button'; class Artist extends React.Component { componentDidMount() { this.setWindowTitle(); this.props.coreActions.loadArtist(this.props.uri); } componentDidUpdate = ({ uri: prevUri, artist: prevArtist, }) => { const { uri, artist, coreActions: { loadArtist, }, } = this.props; if (uri !== prevUri) { loadArtist(uri); } if (!prevArtist && artist) this.setWindowTitle(artist); if (prevUri !== uri && artist) this.setWindowTitle(artist); } onResetFilters = () => { this.onChangeFilter(null); this.onChangeSort(null); } onChangeFilter = (value) => { const { uiActions: { set, hideContextMenu } } = this.props; set({ artist_albums_filter: value }); hideContextMenu(); } 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(); } onPlay = () => { const { artist: { uri, tracks_uris, albums_uris, }, mopidyActions: { playURIs }, } = this.props; playURIs(tracks_uris || 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], }); } loadMore = () => { const { spotifyActions: { getMore }, artist: { albums_more }, uri, } = this.props; getMore( albums_more, { parent_type: 'artist', parent_key: uri, records_type: 'album', }, ); } inLibrary = () => { const { uri } = this.props; const libraryName = `${uriSource(uri)}_library_artists`; const { [libraryName]: library = [] } = this.props; return library.indexOf(uri) > -1; } renderOverview = () => { const { uri, uiActions, artist: artistProp, artists, albums, tracks, sort, sort_reverse, filter, } = this.props; const artist = collate( artistProp, { artists, albums, tracks, }, ); if (sort && artist.albums) { artist.albums = sortItems(artist.albums, sort, sort_reverse); } if (filter && artist.albums) { artist.albums = applyFilter('type', filter, artist.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'), }, { value: 'compilation', label: i18n('artist.albums.filter.compilations'), }, ]; const is_loading_tracks = ( !artist.tracks_uris || (artist.tracks_uris && !artist.tracks) || (artist.tracks_uris.length !== artist.tracks.length) ); return (
0 ? '70' : '100'}`}> {artist.tracks &&

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

)}
{artist.albums && (

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

)}
); } renderTracks = () => { const { artist: artistProp, artists, tracks, } = this.props; const artist = collate( artistProp, { artists, tracks, }, ); const is_loading_tracks = ( !artist.tracks_uris || (artist.tracks_uris && !artist.tracks) || (artist.tracks_uris.length !== artist.tracks.length) ); return (
); } renderRelatedArtists = () => { const { artist: artistProp, artists, } = this.props; const artist = collate( artistProp, { artists, }, ); return (
); } renderAbout = () => { const { artist: artistProp, artists, } = this.props; const artist = collate( artistProp, { artists, }, ); const thumbnails = 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, load_queue, artist, history, } = this.props; if (!artist) { if ( isLoading( load_queue, [`spotify_artists/${getFromUri('artistid', uri)}`, 'lastfm_method=artist.getInfo'], ) ) { return ; } return (

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

{this.props.artist ? this.props.artist.name : null}

{is_spotify && ( )}

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

)} {artist.related_artists_uris && (

)}

{this.renderRelatedArtists()} {this.renderTracks()} {this.renderAbout()} {this.renderOverview()}
); } } const mapStateToProps = (state, ownProps) => { const uri = decodeURIComponent(ownProps.match.params.uri); return { uri, theme: state.ui.theme, slim_mode: state.ui.slim_mode, load_queue: state.ui.load_queue, artist: (state.core.artists[uri] !== undefined ? state.core.artists[uri] : false), tracks: state.core.tracks, artists: state.core.artists, spotify_library_artists: state.spotify.library_artists, local_library_artists: state.mopidy.library_artists, albums: (state.core.albums ? state.core.albums : []), 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), pusherActions: bindActionCreators(pusherActions, dispatch), lastfmActions: bindActionCreators(lastfmActions, dispatch), spotifyActions: bindActionCreators(spotifyActions, dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(Artist);