diff --git a/src/js/services/mopidy/actions.js b/src/js/services/mopidy/actions.js index e405203d..8c18cc5a 100755 --- a/src/js/services/mopidy/actions.js +++ b/src/js/services/mopidy/actions.js @@ -178,6 +178,14 @@ export function getPlaylist( uri ){ } } +export function getPlaylists(uris, processor = null){ + return { + type: 'MOPIDY_GET_PLAYLISTS', + uris: uris, + processor: processor + } +} + export function getDirectory( uri ){ return { type: 'MOPIDY_GET_DIRECTORY', @@ -185,6 +193,12 @@ export function getDirectory( uri ){ } } +export function getLibraryArtists(){ + return { + type: 'MOPIDY_GET_LIBRARY_ARTISTS' + } +} + export function getArtist( uri ){ return { type: 'MOPIDY_GET_ARTIST', @@ -192,9 +206,11 @@ export function getArtist( uri ){ } } -export function getLibraryArtists(){ +export function getArtists(uris, processor = null){ return { - type: 'MOPIDY_GET_LIBRARY_ARTISTS' + type: 'MOPIDY_GET_ARTISTS', + uris: uris, + processor: processor } } diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index a0ea7672..7e3f068f 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -1003,20 +1003,44 @@ const MopidyMiddleware = (function(){ **/ case 'MOPIDY_GET_LIBRARY_ARTISTS': - store.dispatch({ type: 'LOCAL_ARTISTS_LOADED', data: false }); instruct( socket, store, 'library.browse', { uri: 'local:directory?type=artist' } ) - .then( response => { + .then( response => { + if (response.length <= 0) return + + var uris = helpers.arrayOf('uri',response) + store.dispatch({ - type: 'ARTISTS_LOADED', - artists: response - }); - store.dispatch({ - type: 'LOCAL_ARTISTS_LOADED', - uris: helpers.arrayOf('uri',response) + type: 'MOPIDY_LIBRARY_ARTISTS_LOADED', + uris: uris }); + + // Start our process to load the full album objects + store.dispatch(uiActions.startProcess('MOPIDY_LIBRARY_ARTISTS_PROCESSOR','Loading '+uris.length+' local artists', {uris: uris})) }) break; + case 'MOPIDY_LIBRARY_ARTISTS_PROCESSOR': + if (store.getState().ui.processes['MOPIDY_LIBRARY_ARTISTS_PROCESSOR'] !== undefined){ + var processor = store.getState().ui.processes['MOPIDY_LIBRARY_ARTISTS_PROCESSOR'] + + if (processor.cancelling){ + store.dispatch(uiActions.processFinished('MOPIDY_LIBRARY_ARTISTS_PROCESSOR')) + return false + } + } + + var uris = Object.assign([], action.data.uris) + var uris_to_load = uris.splice(0,50) + + if (uris_to_load.length > 0){ + store.dispatch(uiActions.updateProcess('MOPIDY_LIBRARY_ARTISTS_PROCESSOR', 'Loading '+uris.length+' local artists')) + store.dispatch(mopidyActions.getArtists(uris_to_load, {name: 'MOPIDY_LIBRARY_ARTISTS_PROCESSOR', data: {uris: uris}})) + } else { + store.dispatch(uiActions.processFinished('MOPIDY_LIBRARY_ARTISTS_PROCESSOR')) + } + + break + case 'MOPIDY_GET_ARTIST': instruct( socket, store, 'library.lookup', action.data ) .then( response => { @@ -1068,6 +1092,45 @@ const MopidyMiddleware = (function(){ } }) break; + + case 'MOPIDY_GET_ARTISTS': + instruct( socket, store, 'library.lookup', {uris: action.uris}) + .then( response => { + if (response.length <= 0) return + + var artists = [] + + for (var uri in response){ + if (response.hasOwnProperty(uri) && response[uri].length > 0 && response[uri][0].artists){ + var artist = Object.assign( + {}, + (response ? response[uri][0].artists[0] : {}), + { + is_mopidy: true + } + ) + artists.push(artist) + } + } + + store.dispatch({ + type: 'ARTISTS_LOADED', + artists: artists + }) + + // Re-run any consequential processes in 100ms. This allows a small window for other + // server requests before our next batch. It's a little crude but it means the server isn't + // locked until we're completely done. + if (action.processor){ + setTimeout( + function(){ + store.dispatch(uiActions.runProcess(action.processor.name, action.processor.data)) + }, + 100 + ) + } + }) + break; /** diff --git a/src/js/views/library/LibraryAlbums.js b/src/js/views/library/LibraryAlbums.js index aa5ca37d..3900d9db 100755 --- a/src/js/views/library/LibraryAlbums.js +++ b/src/js/views/library/LibraryAlbums.js @@ -212,9 +212,7 @@ class LibraryAlbums extends React.Component{ } } - if (this.props.sort){ - albums = helpers.sortItems(albums, this.props.sort, this.props.sort_reverse) - } + albums = helpers.sortItems(albums, this.props.sort, this.props.sort_reverse) var filter_options = [ { diff --git a/src/js/views/library/LibraryArtists.js b/src/js/views/library/LibraryArtists.js index 74ae10b6..3282be65 100755 --- a/src/js/views/library/LibraryArtists.js +++ b/src/js/views/library/LibraryArtists.js @@ -22,18 +22,40 @@ class LibraryArtists extends React.Component{ } componentDidMount(){ - if (!this.props.spotify_library_artists && this.props.spotify_connected){ - this.props.spotifyActions.getLibraryArtists() + if (!this.props.mopidy_library_artists && this.props.mopidy_connected && (this.props.filter == 'all' || this.props.filter == 'local')){ + this.props.mopidyActions.getLibraryartists() + } + + if (!this.props.spotify_library_artists && this.props.spotify_connected && (this.props.filter == 'all' || this.props.filter == 'spotify')){ + this.props.spotifyActions.getLibraryartists() } } componentWillReceiveProps(newProps){ - if (newProps.spotify_connected){ + if (newProps.mopidy_connected && (newProps.filter == 'all' || newProps.filter == 'local')){ + + // We've just connected + if (!this.props.mopidy_connected){ + this.props.mopidyActions.getLibraryArtists() + } + + // Filter changed, but we haven't got this provider's library yet + if (this.props.filter != 'all' && this.props.filter != 'local' && !newProps.mopidy_library_artists){ + this.props.mopidyActions.getLibraryArtists() + } + } + + if (newProps.spotify_connected && (newProps.filter == 'all' || newProps.filter == 'spotify')){ // We've just connected if (!this.props.spotify_connected){ this.props.spotifyActions.getLibraryArtists() } + + // Filter changed, but we haven't got this provider's library yet + if (this.props.filter != 'all' && this.props.filter != 'spotify' && !newProps.spotify_library_artists){ + this.props.spotifyActions.getLibraryArtists() + } } } @@ -98,6 +120,27 @@ class LibraryArtists extends React.Component{ render(){ var artists = [] + // Mopidy library items + if (this.props.mopidy_library_artists && (this.props.filter == 'all' || this.props.filter == 'local')){ + for (var i = 0; i < this.props.mopidy_library_artists.length; i++){ + + // Construct item placeholder. This is used as Mopidy needs to + // lookup ref objects to get the full object which can take some time + var uri = this.props.mopidy_library_artists[i] + var source = helpers.uriSource(uri) + var artist = { + uri: uri, + source: source + } + + if (this.props.artists.hasOwnProperty(uri)){ + artist = this.props.artists[uri] + } + + artists.push(artist) + } + } + // Spotify library items if (this.props.spotify_library_artists){ for (var i = 0; i < this.props.spotify_library_artists.length; i++){ @@ -110,6 +153,21 @@ class LibraryArtists extends React.Component{ artists = helpers.sortItems(artists, this.props.sort, this.props.sort_reverse) + var filter_options = [ + { + value: 'all', + label: 'All' + }, + { + value: 'local', + label: 'Local' + }, + { + value: 'spotify', + label: 'Spotify' + } + ] + var view_options = [ { label: 'Thumbnails', @@ -138,6 +196,7 @@ class LibraryArtists extends React.Component{ var options = ( + {this.props.uiActions.set({ library_artists_filter: val}); this.props.uiActions.hideContextMenu() }} /> {this.setSort(value); this.props.uiActions.hideContextMenu() }} /> {this.props.uiActions.set({ library_artists_view: value }); this.props.uiActions.hideContextMenu()}} /> @@ -147,7 +206,6 @@ class LibraryArtists extends React.Component{
{ this.renderView(artists) } - this.loadMore() }/>
); } @@ -162,9 +220,12 @@ class LibraryArtists extends React.Component{ const mapStateToProps = (state, ownProps) => { return { + mopidy_connected: state.mopidy.connected, spotify_connected: state.spotify.connected, + mopidy_library_artists: state.mopidy.library_artists, spotify_library_artists: state.spotify.library_artists, artists: state.core.artists, + filter: (state.ui.library_artists_filter ? state.ui.library_artists_filter : 'all'), sort: (state.ui.library_artists_sort ? state.ui.library_artists_sort : 'name'), sort_reverse: (state.ui.library_artists_sort_reverse ? true : false), view: state.core.library_artists_view