Mopidy artist

This commit is contained in:
James Barnsley
2016-11-01 16:41:04 +13:00
parent 5ccd9b48a0
commit 1738c2a29b
15 changed files with 2403 additions and 2172 deletions

View File

@ -1,6 +1,9 @@
RewriteEngine On
RewriteBase /
RewriteRule ^images/(.*)$ http://%{HTTP_HOST}:6680/images/$1 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

View File

@ -3703,6 +3703,7 @@ main header h1 {
.album-view .intro .thumbnail {
float: none;
margin: 0 auto;
max-width: none;
}
.album-view .intro .details {
@ -3774,6 +3775,7 @@ main header h1 {
.playlist-view .intro .thumbnail {
float: none;
margin: 0 auto;
max-width: none;
}
.playlist-view .intro .details {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,11 @@
RewriteEngine On
RewriteBase /
# Handle Mopidy-Images requests
# TODO: Look to move this into the Thumbnail component
RewriteRule ^images/(.*)$ http://%{HTTP_HOST}:6680/images/$1 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

View File

@ -9,9 +9,12 @@ export let SizedImages = function( images ){
huge: false
}
if( images.length > 0 ){
if( images.length <= 0 ) return sizes;
for( var i = 0; i < images.length; i++ ){
for( var i = 0; i < images.length; i++ ){
// spotify-styled images
if( images[i].height ){
if( images[i].height > 800 ){
sizes.huge = images[i].url;
}else if( images[i].height > 600 ){
@ -21,13 +24,17 @@ export let SizedImages = function( images ){
}else{
sizes.small = images[i].url;
}
}
if( !sizes.medium ) sizes.medium = sizes.small;
if( !sizes.large ) sizes.large = sizes.medium;
if( !sizes.huge ) sizes.huge = sizes.large;
// Mopidy-Images styled images
}else if( typeof(images[i]) == 'string' ){
sizes.small = images[i]
}
}
if( !sizes.medium ) sizes.medium = sizes.small;
if( !sizes.large ) sizes.large = sizes.medium;
if( !sizes.huge ) sizes.huge = sizes.large;
return sizes;
}

View File

@ -38,25 +38,25 @@ ReactDOM.render(
<Route path="/" component={App}>
<IndexRoute component={Queue} />
<Route path="/queue" component={Queue} />
<Route path="queue" component={Queue} />
<Route path="/discover" component={Discover} />
<Route path="/discover/featured" component={DiscoverFeatured} />
<Route path="/discover/categories" component={DiscoverCategories} />
<Route path="/discover/categories/:id" component={DiscoverCategory} />
<Route path="/discover/new-releases" component={DiscoverNewReleases} />
<Route path="discover" component={Discover} />
<Route path="discover/featured" component={DiscoverFeatured} />
<Route path="discover/categories" component={DiscoverCategories} />
<Route path="discover/categories/:id" component={DiscoverCategory} />
<Route path="discover/new-releases" component={DiscoverNewReleases} />
<Route path="/library/artists" component={LibraryArtists} />
<Route path="/library/albums" component={LibraryAlbums} />
<Route path="/library/tracks" component={LibraryTracks} />
<Route path="/library/playlists" component={LibraryPlaylists} />
<Route path="/library/local" component={LibraryLocal} />
<Route path="/library/local/directory/:uri" component={LibraryLocalDirectory} />
<Route path="library/artists" component={LibraryArtists} />
<Route path="library/albums" component={LibraryAlbums} />
<Route path="library/tracks" component={LibraryTracks} />
<Route path="library/playlists" component={LibraryPlaylists} />
<Route path="library/local" component={LibraryLocal} />
<Route path="library/local/directory/:uri" component={LibraryLocalDirectory} />
<Route path="/album/:uri" component={Album} />
<Route path="/artist/:uri" component={Artist} />
<Route path="/playlist/:uri" component={Playlist} />
<Route path="/settings" component={Settings} />
<Route path="album/:uri" component={Album} />
<Route path="artist/:uri" component={Artist} />
<Route path="playlist/:uri" component={Playlist} />
<Route path="settings" component={Settings} />
</Route>
</Router>

View File

@ -117,3 +117,10 @@ export function getAlbum( uri ){
}
}
export function getArtist( uri ){
return {
type: 'MOPIDY_ARTIST',
data: { uri: uri }
}
}

View File

@ -199,6 +199,7 @@ const MopidyMiddleware = (function(){
instruct( socket, store, 'library.lookup', action.data )
.then( response => {
var album = response[0].album;
album.artists = response[0].artists;
album.tracks = {
items: response,
total: response.length
@ -236,6 +237,32 @@ const MopidyMiddleware = (function(){
})
break;
case 'MOPIDY_ARTIST':
instruct( socket, store, 'library.lookup', action.data )
.then( response => {
var artist = {
name: 'yeah',
images: [],
albums: [],
tracks: response.slice(0,10)
}
for( var i = 0; i < response.length; i++ ){
var album = response[i].album;
function getByURI( albumToCheck ){
return album.uri == albumToCheck.uri
}
var existingAlbum = artist.albums.find(getByURI);
if( !existingAlbum ){
artist.albums.push(album)
}
}
store.dispatch({ type: 'MOPIDY_ARTIST_LOADED', data: artist });
})
break;
// This action is irrelevant to us, pass it on to the next middleware
default:
return next(action);

View File

@ -87,6 +87,11 @@ export default function reducer(mopidy = {}, action){
album: action.data
});
case 'MOPIDY_ARTIST_LOADED':
return Object.assign({}, mopidy, {
artist: action.data
});
default:
return mopidy
}

View File

@ -20,7 +20,6 @@ class Album extends React.Component{
super(props);
}
// on render
componentDidMount(){
this.loadAlbum();
}
@ -44,12 +43,11 @@ class Album extends React.Component{
}
}
totalTime(){
if( !this.props.spotify.album ) return null
var tracks = this.props.spotify.tracks.items;
totalTime( tracks = [] ){
var duration = 0;
for( var i = 0; i < tracks.length; i++ ){
duration += tracks[i].duration_ms;
if( tracks[i].duration_ms ) duration += parseInt(tracks[i].duration_ms);
if( tracks[i].length ) duration += parseInt(tracks[i].length);
}
return duration;
}
@ -63,11 +61,11 @@ class Album extends React.Component{
return (
<div className="view album-view">
<div className="intro">
<Thumbnail size="large" images={ album.images } />
<Thumbnail size="large" images={ ( album.images ? album.images : [] ) } />
<ArtistGrid artists={ album.artists } />
<div className="details">
<div>{ album.tracks.total } tracks, { this.totalTime }</div>
<div>Released <Dater type="date" data={ album.release_date } /></div>
<div>{ album.tracks.total } tracks, <Dater type="length" data={this.totalTime(album.tracks.items)} /> mins</div>
{ album.release_date ? <div>Released <Dater type="date" data={ album.release_date } /></div> : null }
</div>
</div>
<div className="main">

View File

@ -2,6 +2,7 @@
import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
let helpers = require('../helpers.js')
import LazyLoadListener from '../components/LazyLoadListener'
import Header from '../components/Header'
@ -11,6 +12,7 @@ import Thumbnail from '../components/Thumbnail'
import Parallax from '../components/Parallax'
import ArtistList from '../components/ArtistList'
import * as mopidyActions from '../services/mopidy/actions'
import * as spotifyActions from '../services/spotify/actions'
class Artist extends React.Component{
@ -19,15 +21,26 @@ class Artist extends React.Component{
super(props);
}
// on render
componentDidMount(){
this.props.spotifyActions.getArtist( this.props.params.uri );
this.loadArtist();
}
// when props changed
componentWillReceiveProps( nextProps ){
if( nextProps.params.uri != this.props.params.uri ){
this.props.spotifyActions.getArtist( nextProps.params.uri );
this.loadArtist( nextProps )
}else if( !this.props.mopidy.connected && nextProps.mopidy.connected ){
if( helpers.uriSource( this.props.params.uri ) == 'local' ){
this.loadArtist( nextProps )
}
}
}
loadArtist( props = this.props ){
var source = helpers.uriSource( props.params.uri );
if( source == 'spotify' ){
this.props.spotifyActions.getArtist( props.params.uri );
}else if( source == 'local' && props.mopidy.connected ){
this.props.mopidyActions.getArtist( props.params.uri );
}
}
@ -36,39 +49,79 @@ class Artist extends React.Component{
this.props.spotifyActions.getURL( this.props.spotify.artist_albums.next, 'SPOTIFY_ARTIST_ALBUMS_LOADED_MORE' );
}
render(){
if( this.props.spotify.artist ){
return (
<div className="view artist-view">
<Parallax images={ this.props.spotify.artist.images } />
renderSpotifyAlbum(){
if( !this.props.spotify.artist ) return null
var artist = this.props.spotify.artist
var albums = this.props.spotify.artist_albums
<div className="intro">
<Thumbnail size="huge" images={ this.props.spotify.artist.images } />
<h1>{ this.props.spotify.artist.name }</h1>
<p>{ this.props.spotify.artist.followers.total.toLocaleString() } followers</p>
</div>
return (
<div className="view artist-view">
<Parallax images={ artist.images } />
<div className="col w70">
<h4 className="left-padding">Top tracks</h4>
{ this.props.spotify.artist.tracks ? <TrackList tracks={ this.props.spotify.artist.tracks } /> : null }
</div>
<div className="col w5"></div>
<div className="col w25">
<h4>Related artists</h4>
{ this.props.spotify.artist.related_artists ? <ArtistList artists={ this.props.spotify.artist.related_artists.slice(0,6) } /> : null }
</div>
<div className="cf"></div>
<h4 className="left-padding">Albums</h4>
{ this.props.spotify.artist_albums ? <AlbumGrid className="no-top-padding" albums={ this.props.spotify.artist_albums.items } /> : null }
<LazyLoadListener loadMore={ () => this.loadMore() }/>
<div className="intro">
<Thumbnail size="huge" images={ artist.images } />
<h1>{ artist.name }</h1>
<p>{ artist.followers.total.toLocaleString() } followers</p>
</div>
);
}
return null;
<div className="col w70">
<h4 className="left-padding">Top tracks</h4>
{ artist.tracks ? <TrackList tracks={ artist.tracks } /> : null }
</div>
<div className="col w5"></div>
<div className="col w25">
<h4>Related artists</h4>
{ artist.related_artists ? <ArtistList artists={ artist.related_artists.slice(0,6) } /> : null }
</div>
<div className="cf"></div>
<h4 className="left-padding">Albums</h4>
{ albums ? <AlbumGrid className="no-top-padding" albums={ albums.items } /> : null }
<LazyLoadListener loadMore={ () => this.loadMore() }/>
</div>
);
}
renderMopidyAlbum(){
if( !this.props.mopidy.artist ) return null
var artist = this.props.mopidy.artist
return (
<div className="view artist-view">
<Parallax images={ artist.images } />
<div className="intro">
<Thumbnail size="huge" images={ artist.images } />
<h1>{ artist.name }</h1>
</div>
<div className="col w70">
<h4 className="left-padding">Top tracks</h4>
{ artist.tracks ? <TrackList tracks={ artist.tracks } /> : null }
</div>
<div className="col w5"></div>
<div className="col w25">
<h4>Related artists</h4>
{ artist.related_artists ? <ArtistList artists={ artist.artist.related_artists.slice(0,6) } /> : null }
</div>
<div className="cf"></div>
<h4 className="left-padding">Albums</h4>
{ artist.albums ? <AlbumGrid className="no-top-padding" albums={ artist.albums } /> : null }
</div>
);
}
render(){
var source = helpers.uriSource( this.props.params.uri );
if( source == 'spotify' ) return this.renderSpotifyAlbum()
if( source == 'local' ) return this.renderMopidyAlbum()
}
}
@ -85,6 +138,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => {
return {
mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch)
}
}

View File

@ -26,6 +26,7 @@
.thumbnail {
float: none;
margin: 0 auto;
max-width: none;
}
.details {

View File

@ -26,6 +26,7 @@
.thumbnail {
float: none;
margin: 0 auto;
max-width: none;
}
.details {