Moving more playlist functions to the pool

This commit is contained in:
James Barnsley
2017-01-14 01:01:48 +13:00
parent 8b718c0a33
commit c5bb4ee6ca
12 changed files with 157 additions and 98 deletions

View File

@ -20,5 +20,7 @@ CACHEBUSTER=$(date | md5sum | cut -f1 -d' ')
echo -e Cachebusting js/css URLs $CACHEBUSTER
sed -i 's/app.js/app.min.js?'$CACHEBUSTER'/g' mopidy_iris/static/index.html
sed -i 's/app.css/app.min.css?'$CACHEBUSTER'/g' mopidy_iris/static/index.html
sed -i 's/app.js/app.js?'$CACHEBUSTER'/g' mopidy_iris/static/test.html
sed -i 's/app.css/app.css?'$CACHEBUSTER'/g' mopidy_iris/static/test.html
echo -e "\x1b[32;01m"Done!"\x1b[39;49;00m"

View File

@ -30,7 +30,21 @@ class FollowButton extends React.Component{
render(){
if( !this.props.spotify_authorized || !this.props.uri ) return false
var item = this.props[helpers.uriType( this.props.uri )]
var item = {}
switch (helpers.uriType( this.props.uri )){
case 'artist':
item = this.props.artists[this.props.uri]
break
case 'user':
item = this.props.users[this.props.uri]
break
case 'album':
item = this.props.albums[this.props.uri]
break
case 'playlist':
item = this.props.playlists[this.props.uri]
break
}
if( item.following === true ){
return <button className="tertiary large" onClick={ () => this.remove() }>{ this.props.removeText }</button>
@ -43,10 +57,10 @@ class FollowButton extends React.Component{
const mapStateToProps = (state, ownProps) => {
return {
spotify_authorized: state.spotify.authorized,
artist: state.ui.artist,
user: state.ui.user,
album: state.ui.album,
playlist: state.ui.playlist
artists: state.ui.artists,
users: state.ui.users,
albums: state.ui.albums,
playlists: state.ui.playlists
}
}

View File

@ -24,6 +24,32 @@ export default class GridItem extends React.Component{
return <Thumbnail size="medium" images={[]} />
}
renderSecondary(item){
var output = ''
switch (item.type){
case 'playlist':
return (
<span>
{ item.tracks_total ? item.tracks_total+' tracks' : null }
{ item.can_edit ? <FontAwesome name="edit" /> : null }
</span>
)
break
default:
return (
<span>
{ item.artists ? <ArtistSentence artists={ item.artists } /> : null }
{ item.followers ? item.followers.total.toLocaleString()+' followers' : null }
</span>
)
}
return output
}
render(){
if( !this.props.item ) return null
@ -37,10 +63,7 @@ export default class GridItem extends React.Component{
{ this.renderThumbnail() }
<div className="name">{ item.name }</div>
<div className="secondary">
{ item.artists ? <ArtistSentence artists={ item.artists } /> : null }
{ item.type == 'playlist' && item.tracks_total ? item.tracks_total+' tracks' : null }
{ item.followers ? item.followers.total.toLocaleString()+' followers' : null }
{ item.type == 'playlist' && item.can_edit ? <FontAwesome name="edit" /> : null }
{ this.renderSecondary(item) }
</div>
</div>
);

View File

@ -196,6 +196,18 @@ export let uriType = function( uri ){
}
/**
* Convert a raw URI into a object index-friendly format. Primarily used for loading local playlists
* @param $uri = string
* @return string
**/
export let indexFriendlyUri = function (uri){
var output = encodeURI(uri)
output = output.replace("'",'%27')
return output
}
/**
* Digest an array of objects, and pull into simple array of uris
*

View File

@ -12,7 +12,7 @@ const localstorageMiddleware = (function(){
// append our state to a global variable. This gives us access to debug the store at any point
window._store = store
console.log(action)
//console.log(action)
switch( action.type ){

View File

@ -304,14 +304,11 @@ const MopidyMiddleware = (function(){
var playlist = Object.assign(
{},
{
images: []
},
{
can_edit: (response.uri.startsWith('m3u:'))
},
response,
{
tracks: ( response.tracks ? response.tracks : [] ),
type: 'playlist',
name: response.name,
uri: response.uri,
last_modified: response.last_modified,
can_edit: (response.uri.startsWith('m3u:')),
tracks_total: ( response.tracks ? response.tracks.length : 0 )
}
)
@ -328,18 +325,16 @@ const MopidyMiddleware = (function(){
.then( response => {
var playlist = Object.assign(
{},
{
images: []
},
response,
{
tracks: ( response.tracks ? response.tracks : [] ),
tracks_total: ( response.tracks ? response.tracks.length : 0 )
type: 'playlist',
tracks: ( response.tracks ? response.tracks : null ),
tracks_total: ( response.tracks ? response.tracks.length : null )
}
)
// tracks? get the full track objects
if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_RESOLVE_PLAYLIST_TRACKS', tracks: playlist.tracks })
if( playlist.tracks.length > 0 ) store.dispatch({ type: 'MOPIDY_RESOLVE_PLAYLIST_TRACKS', tracks: playlist.tracks, uri: response.uri })
store.dispatch({ type: 'PLAYLIST_LOADED', playlist: playlist })
})
@ -372,7 +367,7 @@ const MopidyMiddleware = (function(){
}
}
store.dispatch({ type: 'PLAYLIST_TRACKS_LOADED', playlist_uri: action.playlist_uri, tracks: tracks })
store.dispatch({ type: 'PLAYLIST_TRACKS_RESOLVED', tracks: tracks, uri: action.uri })
})
break

View File

@ -263,9 +263,19 @@ export function getFeaturedPlaylists(){
sendRequest( dispatch, getState, 'browse/featured-playlists?timestamp='+timestamp+'&country='+getState().spotify.country+'&limit=50&locale='+getState().spotify.locale )
.then( response => {
for (var i = 0; i < response.playlists.items.length; i++){
var playlist = response.playlists.items[i]
Object.assign(
playlist,
{
can_edit: (getState().spotify.me && playlist.owner.id == getState().spotify.me.id),
tracks_total: playlist.tracks.total
}
)
dispatch({
type: 'PLAYLIST_LOADED',
playlist: response.playlists.items[i]
playlist: playlist
});
}
dispatch({
@ -306,18 +316,22 @@ export function getCategory( id ){
).then( ( category_response, playlists_response ) => {
var playlists = []
for (var i = 0; i < playlists_response.playlists.items.length; i++){
playlists.push(
Object.assign(
{},
playlists_response.playlists.items[i],
{
tracks: false,
tracks_total: playlists_response.playlists.items[i].tracks.total
}
)
var playlist = Object.assign(
{},
playlists_response.playlists.items[i],
{
tracks: null,
tracks_more: null,
tracks_total: playlists_response.playlists.items[i].tracks.total
}
)
dispatch({
type: 'PLAYLIST_LOADED',
playlist: playlist
});
}
var category = Object.assign(
@ -325,10 +339,14 @@ export function getCategory( id ){
category_response,
{
items: false,
playlists: playlists
playlists: helpers.asURIs(playlists_response.playlists.items),
playlists_more: playlists_response.playlists.next,
playlists_total: playlists_response.playlists.total
}
)
console.log(category)
dispatch({
type: 'SPOTIFY_CATEGORY_LOADED',
data: category
@ -358,8 +376,8 @@ export function getURL( url, action_name, uri = false ){
.then( response => {
dispatch({
type: action_name,
data: response,
uri: uri
uri: uri,
data: response
});
});
}
@ -829,27 +847,20 @@ function loadNextPlaylistsBatch( dispatch, getState, playlists, lastResponse ){
});
}else{
// check our editability of each playlist
// used to define what we can add tracks to
if( getState().spotify.authorized ){
for( var i = 0; i < playlists.length; i++ ){
for( var i = 0; i < playlists.length; i++ ){
var playlist = Object.assign(
{},
playlists[i],
{
can_edit: (getState().spotify.authorized && getState().spotify.me && playlists[i].owner.id == getState().spotify.me.id),
tracks_total: playlists[i].tracks.total
}
)
var playlist = Object.assign(
{},
playlists[i],
{
can_edit: (getState().spotify.me && playlists[i].owner.id == getState().spotify.me.id),
tracks: helpers.flattenTracks(playlists[i].tracks.items),
tracks_more: response.tracks.next,
tracks_total: response.tracks.total
}
)
dispatch({
type: 'PLAYLIST_LOADED',
playlist: playlist
});
}
dispatch({
type: 'PLAYLIST_LOADED',
playlist: playlist
});
}
dispatch({

View File

@ -156,9 +156,7 @@ export default function reducer(spotify = {}, action){
case 'SPOTIFY_CATEGORY_LOADED':
return Object.assign({}, spotify, { category: action.data })
case 'SPOTIFY_CATEGORY_PLAYLISTS_LOADED':
return Object.assign({}, spotify, { category_playlists: action.data })
// TODO: update this
case 'SPOTIFY_CATEGORY_PLAYLISTS_LOADED_MORE':
return Object.assign({}, spotify, { category_playlists: {
href: action.data.href,

View File

@ -114,9 +114,6 @@ export default function reducer(ui = {}, action){
current_track: current_track
});
case 'FOLLOWING_LOADING':
return Object.assign({}, ui, { following_loading: true })
case 'RADIO':
case 'START_RADIO':
return Object.assign({}, ui, { seeds_resolved: false }, { radio: action.data.radio })
@ -223,17 +220,25 @@ export default function reducer(ui = {}, action){
* Playlists
**/
case 'PLAYLIST_LOADED':
case 'PLAYLIST_UPDATED':
var playlist = Object.assign({}, ui.playlist, action.playlist)
return Object.assign({}, ui, { playlist: playlist })
var playlists = Object.assign([], ui.playlists)
var playlist = Object.assign({}, action.playlist)
// if we already have one in our list, fetch it and update it
if (playlists[action.playlist.uri]){
playlist = Object.assign({}, playlists[action.playlist.uri], action.playlist)
}
playlists[action.playlist.uri] = playlist
return Object.assign({}, ui, { playlists: playlists });
case 'MOPIDY_PLAYLIST_LOADED':
if( !action.data ) return Object.assign({}, ui, { playlist: false })
return Object.assign({}, ui, { playlist: action.data })
case 'PLAYLIST_LOADED_MORE_TRACKS':
var playlists = ui.playlists
var playlists = Object.assign([], ui.playlists)
var playlist = Object.assign(
{},
playlists[action.uri],
@ -258,9 +263,12 @@ export default function reducer(ui = {}, action){
var playlist = Object.assign({}, ui.playlist, { tracks: tracks, snapshot_id: snapshot_id })
return Object.assign({}, ui, { playlist: playlist });
case 'PLAYLIST_TRACKS_LOADED':
var playlist = Object.assign({}, ui.playlist, { tracks: action.tracks })
return Object.assign({}, ui, { playlist: playlist });
case 'PLAYLIST_TRACKS_RESOLVED':
var playlists = Object.assign([], ui.playlists)
var playlist = Object.assign({}, playlists[action.uri], { tracks: action.tracks })
playlists[action.uri] = playlist
return Object.assign({}, ui, { playlists: playlists });
case 'PLAYLIST_TRACKS_REORDERED':
var snapshot_id = null
@ -283,25 +291,10 @@ export default function reducer(ui = {}, action){
return Object.assign({}, ui, { playlist: playlist });
case 'PLAYLIST_FOLLOWING_LOADED':
var playlist = Object.assign({}, ui.playlist, { following: action.is_following })
return Object.assign({}, ui, { playlist: playlist, following_loading: false });
var playlists = Object.assign([], ui.playlists)
var playlist = Object.assign({}, playlists[action.uri], { following: action.is_following })
/**
* Library Playlists
**/
case 'PLAYLIST_LOADED':
case 'PLAYLIST_UPDATED':
var playlists = ui.playlists
var playlist = Object.assign({}, action.playlist)
// if we already have one in our list, fetch it and update it
if (playlists[action.playlist.uri]){
playlist = Object.assign({}, playlists[action.playlist.uri], action.playlist)
}
playlists[action.playlist.uri] = playlist
playlists[action.uri] = playlist
return Object.assign({}, ui, { playlists: playlists });
case 'LIBRARY_PLAYLISTS_LOADED':

View File

@ -173,7 +173,7 @@ class Playlist extends React.Component{
const mapStateToProps = (state, ownProps) => {
return {
playlist: state.ui.playlists[ownProps.params.uri],
playlist: state.ui.playlists[helpers.indexFriendlyUri(ownProps.params.uri)],
mopidy_connected: state.mopidy.connected,
spotify_authorized: state.spotify.authorized,
spotify_userid: state.spotify.me.id

View File

@ -26,18 +26,26 @@ class DiscoverCategory extends React.Component{
}
loadMore(){
if( !this.props.spotify.new_releases || !this.props.spotify.new_releases.next ) return
this.props.spotifyActions.getURL( this.props.spotify.new_releases.next, 'SPOTIFY_NEW_RELEASES_LOADED_MORE' );
if( !this.props.playlists_next || !this.props.playlists_next ) return
this.props.spotifyActions.getURL( this.props.playlists_next, 'SPOTIFY_NEW_RELEASES_LOADED_MORE' );
}
render(){
if( !this.props.spotify.category ) return null;
if (!this.props.category) return null
var playlists = []
for (var i = 0; i < this.props.category.playlists.length; i++){
var uri = this.props.category.playlists[i]
if (this.props.playlists.hasOwnProperty(uri)){
playlists.push(this.props.playlists[uri])
}
}
return (
<div className="view discover-categories-view">
<Header icon="grid" title={this.props.spotify.category.name} />
<Header icon="grid" title={this.props.category.name} />
<section className="grid-wrapper">
{ this.props.spotify.category.playlists ? <PlaylistGrid playlists={this.props.spotify.category.playlists} /> : null }
<PlaylistGrid playlists={playlists} />
</section>
<LazyLoadListener loadMore={ () => this.loadMore() }/>
</div>
@ -53,7 +61,10 @@ class DiscoverCategory extends React.Component{
**/
const mapStateToProps = (state, ownProps) => {
return state;
return {
playlists: state.ui.playlists,
category: state.spotify.category
}
}
const mapDispatchToProps = (dispatch) => {

View File

@ -67,7 +67,7 @@ class LibraryPlaylists extends React.Component{
{
width: 10,
label: 'Tracks',
name: 'tracks.total'
name: 'tracks_total'
}
]
return (