diff --git a/build.sh b/build.sh index aced77c7..879480a0 100755 --- a/build.sh +++ b/build.sh @@ -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" \ No newline at end of file diff --git a/src/js/components/FollowButton.js b/src/js/components/FollowButton.js index 0e65d0a1..42e62ce2 100755 --- a/src/js/components/FollowButton.js +++ b/src/js/components/FollowButton.js @@ -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 @@ -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 } } diff --git a/src/js/components/GridItem.js b/src/js/components/GridItem.js index bd3a2d50..addbd4f2 100755 --- a/src/js/components/GridItem.js +++ b/src/js/components/GridItem.js @@ -24,6 +24,32 @@ export default class GridItem extends React.Component{ return } + renderSecondary(item){ + var output = '' + + switch (item.type){ + + case 'playlist': + return ( + + { item.tracks_total ? item.tracks_total+' tracks' : null } + { item.can_edit ? : null } + + ) + break + + default: + return ( + + { item.artists ? : null } + { item.followers ? item.followers.total.toLocaleString()+' followers' : null } + + ) + } + + return output + } + render(){ if( !this.props.item ) return null @@ -37,10 +63,7 @@ export default class GridItem extends React.Component{ { this.renderThumbnail() }
{ item.name }
- { 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 ? : null } + { this.renderSecondary(item) }
); diff --git a/src/js/helpers.js b/src/js/helpers.js index 17cb6a8c..15e74f08 100755 --- a/src/js/helpers.js +++ b/src/js/helpers.js @@ -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 * diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index 435627b4..b04cc042 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -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 ){ diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index f10054fe..edc1b07f 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -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 diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index 4034ae29..e6046f44 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -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({ diff --git a/src/js/services/spotify/reducer.js b/src/js/services/spotify/reducer.js index cd91ae27..9168d64f 100755 --- a/src/js/services/spotify/reducer.js +++ b/src/js/services/spotify/reducer.js @@ -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, diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index a7024819..f9d29fc3 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -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': diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js index faa42ca4..55927ceb 100755 --- a/src/js/views/Playlist.js +++ b/src/js/views/Playlist.js @@ -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 diff --git a/src/js/views/discover/DiscoverCategory.js b/src/js/views/discover/DiscoverCategory.js index 769f1188..a22f5026 100755 --- a/src/js/views/discover/DiscoverCategory.js +++ b/src/js/views/discover/DiscoverCategory.js @@ -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 (
-
+
- { this.props.spotify.category.playlists ? : null } +
this.loadMore() }/>
@@ -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) => { diff --git a/src/js/views/library/LibraryPlaylists.js b/src/js/views/library/LibraryPlaylists.js index f4f2ef00..8d8273a5 100755 --- a/src/js/views/library/LibraryPlaylists.js +++ b/src/js/views/library/LibraryPlaylists.js @@ -67,7 +67,7 @@ class LibraryPlaylists extends React.Component{ { width: 10, label: 'Tracks', - name: 'tracks.total' + name: 'tracks_total' } ] return (