From d5e2b56d95ddc466cd4fc7a87d15c963d20ee44d Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 13 Nov 2017 16:52:53 +1300 Subject: [PATCH] Recommendations in track index --- .../components/LastfmAuthenticationFrame.js | 2 +- src/js/services/spotify/actions.js | 27 ++-- src/js/services/spotify/reducer.js | 7 +- src/js/views/Settings.js | 115 +++++++++++------- .../views/discover/DiscoverRecommendations.js | 36 ++++-- 5 files changed, 118 insertions(+), 69 deletions(-) diff --git a/src/js/components/LastfmAuthenticationFrame.js b/src/js/components/LastfmAuthenticationFrame.js index 50e0e536..2eecd9eb 100755 --- a/src/js/components/LastfmAuthenticationFrame.js +++ b/src/js/components/LastfmAuthenticationFrame.js @@ -54,7 +54,7 @@ class LastfmAuthenticationFrame extends React.Component{ } // Turn off our authorizing switch - this.setState({authorizing: false}) + this.setState({authorizing: false}); } startAuthorization(){ diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index fdbf4d48..756cc3b9 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -869,7 +869,7 @@ export function getFavorites(limit = 50, term = 'long_term'){ export function getRecommendations(uris = [], limit = 20){ return (dispatch, getState) => { - dispatch({type: 'SPOTIFY_RECOMMENDATIONS_LOADED', tracks: [], artists_uris: [], albums_uris: []}) + dispatch({type: 'CLEAR_SPOTIFY_RECOMMENDATIONS'}); // build our starting point var artists_ids = [] @@ -909,15 +909,16 @@ export function getRecommendations(uris = [], limit = 20){ sendRequest(dispatch, getState, endpoint) .then( response => { + var tracks = Object.assign([], response.tracks); // We only get simple artist objects, so we need to // get the full object. We'll add URIs to our recommendations // anyway so we can proceed in the meantime var artists_uris = [] - if (response.tracks.length > artists_ids.length && response.tracks.length > 10){ + if (tracks.length > artists_ids.length && tracks.length > 10){ while (artists_uris.length < 5){ - var random_index = Math.round(Math.random() * (response.tracks.length - 1)) - var artist = response.tracks[random_index].artists[0] + var random_index = Math.round(Math.random() * (tracks.length - 1)) + var artist = tracks[random_index].artists[0] // Make sure this artist is not already in our sample, and // is not one of the seeds @@ -931,10 +932,10 @@ export function getRecommendations(uris = [], limit = 20){ // Copy already loaded albums into array var albums = [] var albums_uris = [] - if (response.tracks.length > 10){ + if (tracks.length > 10){ while (albums.length < 5){ - var random_index = Math.round(Math.random() * (response.tracks.length - 1)) - var album = response.tracks[random_index].album + var random_index = Math.round(Math.random() * (tracks.length - 1)) + var album = tracks[random_index].album // Make sure this album is not already in our sample if (!albums_uris.includes(album.uri)){ @@ -944,19 +945,23 @@ export function getRecommendations(uris = [], limit = 20){ } } - // Officially add albums to index dispatch({ type: 'ALBUMS_LOADED', albums: albums - }) + }); + + dispatch({ + type: 'TRACKS_LOADED', + tracks: tracks + }); dispatch({ type: 'SPOTIFY_RECOMMENDATIONS_LOADED', seeds_uris: uris, - tracks: response.tracks, + tracks_uris: helpers.arrayOf('uri',tracks), artists_uris: artists_uris, albums_uris: helpers.arrayOf('uri',albums) - }) + }); }, error => { dispatch(coreActions.handleException( diff --git a/src/js/services/spotify/reducer.js b/src/js/services/spotify/reducer.js index 596db1e8..cdf1410a 100755 --- a/src/js/services/spotify/reducer.js +++ b/src/js/services/spotify/reducer.js @@ -105,6 +105,9 @@ export default function reducer(spotify = {}, action){ } ); + case 'CLEAR_SPOTIFY_RECOMMENDATIONS': + return Object.assign({}, spotify, {recommendations: {artists_uris: [], albums_uris: [], tracks_uris: []}}); + case 'SPOTIFY_RECOMMENDATIONS_LOADED': return Object.assign( {}, @@ -113,9 +116,9 @@ export default function reducer(spotify = {}, action){ recommendations: { artists_uris: action.artists_uris, albums_uris: action.albums_uris, - tracks: helpers.formatTracks(action.tracks) + tracks_uris: action.tracks_uris } - }) + }); case 'SPOTIFY_FAVORITES_LOADED': return Object.assign( diff --git a/src/js/views/Settings.js b/src/js/views/Settings.js index 56cede47..19bc02fa 100755 --- a/src/js/views/Settings.js +++ b/src/js/views/Settings.js @@ -38,6 +38,12 @@ class Settings extends React.Component { } } + componentDidMount(){ + if (this.props.lastfm.session && this.props.core.users["lastfm:user:"+this.props.lastfm.session.name] === undefined){ + this.props.lastfmActions.getMe(); + } + } + componentWillReceiveProps(newProps){ var changed = false var state = this.state @@ -107,7 +113,7 @@ class Settings extends React.Component { } renderSpotifyUser(){ - var user = this.props.spotify.me + var user = this.props.spotify.me; if (user){ return ( @@ -165,43 +171,59 @@ class Settings extends React.Component { ) } - renderServiceStatus(service){ - let colour = 'red' - let icon = 'close' - let name = service.charAt(0).toUpperCase() + service.slice(1).toLowerCase() - let text = 'Disconnected' - let tooltip = null - service = this.props[service] + renderServerStatus(){ + var colour = 'grey'; + var icon = 'question-circle'; + var status = 'Unknown'; - if (service.connecting){ - icon = 'plug' - colour = 'grey' - text = 'Connecting' - } else if (name == 'Spotify' && (!this.props.mopidy.uri_schemes || !this.props.mopidy.uri_schemes.includes('spotify:'))){ - icon = 'exclamation-triangle' - colour = 'red' - text = 'Not installed' - tooltip = 'Mopidy-Spotify is not installed or enabled' - } else if (service.connected){ - icon = 'check' - colour = 'green' - text = 'Connected' + if (this.props.mopidy.connecting || this.props.pusher.connecting){ + icon = 'plug'; + status = 'Connecting...' + } else if (!this.props.mopidy.connected || !this.props.pusher.connected){ + colour = 'red'; + icon = 'close'; + status = 'Disconnected'; + } else if (this.props.mopidy.connected && this.props.pusher.connected){ + colour = 'green'; + icon = 'check'; + status = 'Connected'; } return ( -
-

- {name} -

-
- -
-
- {text} -
- {tooltip ? {tooltip} : null} -
- ) + +   {status} + + ); + } + + renderSpotifyStatus(){ + var colour = 'grey'; + var icon = 'question-circle'; + var status = 'Unknown'; + + if (this.props.spotify.connecting){ + icon = 'plug'; + status = 'Connecting...' + } else if (!this.props.spotify.connected){ + colour = 'red'; + icon = 'close'; + status = 'Disconnected'; + } else if (this.props.mopidy.connected){ + colour = 'green'; + icon = 'check'; + status = 'Connected'; + } + + if (!this.props.mopidy.uri_schemes || !this.props.mopidy.uri_schemes.includes('spotify:')){ + colour = 'orange'; + status += ' (Mopidy-Spotify extension not installed/enabled!)'; + } + + return ( + +   {status} + + ); } render(){ @@ -232,17 +254,17 @@ class Settings extends React.Component {
-

Services

+

Server

-
- {this.renderServiceStatus('mopidy')} - {this.renderServiceStatus('pusher')} - {this.renderServiceStatus('spotify')} - {this.renderServiceStatus('lastfm')} +
+
Status
+
+
+ {this.renderServerStatus()} +
+
-

System

-
Username
@@ -317,6 +339,15 @@ class Settings extends React.Component {

Spotify

+
+
Status
+
+
+ {this.renderSpotifyStatus()} +
+
+
+
Current user
diff --git a/src/js/views/discover/DiscoverRecommendations.js b/src/js/views/discover/DiscoverRecommendations.js index a7d9b015..47a18d01 100755 --- a/src/js/views/discover/DiscoverRecommendations.js +++ b/src/js/views/discover/DiscoverRecommendations.js @@ -178,32 +178,42 @@ class Discover extends React.Component{ } if (!this.props.recommendations || typeof(this.props.recommendations.albums_uris) === 'undefined' || typeof(this.props.recommendations.artists_uris) === 'undefined'){ - return null + return null; } - var albums = [] + var albums = []; if (this.props.recommendations.albums_uris && this.props.albums){ for (var i = 0; i < this.props.recommendations.albums_uris.length; i++){ - var uri = this.props.recommendations.albums_uris[i] + var uri = this.props.recommendations.albums_uris[i]; if (this.props.albums.hasOwnProperty(uri)){ - albums.push(this.props.albums[uri]) + albums.push(this.props.albums[uri]); } } } - var artists = [] + var artists = []; if (this.props.recommendations.artists_uris && this.props.artists){ for (var i = 0; i < this.props.recommendations.artists_uris.length; i++){ - var uri = this.props.recommendations.artists_uris[i] + var uri = this.props.recommendations.artists_uris[i]; if (this.props.artists.hasOwnProperty(uri)){ - artists.push(this.props.artists[uri]) + artists.push(this.props.artists[uri]); } } } - var uri = 'iris:discover' + var tracks = []; + if (this.props.recommendations.tracks_uris && this.props.tracks){ + for (var i = 0; i < this.props.recommendations.tracks_uris.length; i++){ + var uri = this.props.recommendations.tracks_uris[i]; + if (this.props.tracks.hasOwnProperty(uri)){ + tracks.push(this.props.tracks[uri]); + } + } + } + + var uri = 'iris:discover'; if (this.props.params.seeds){ - uri += ':'+this.props.params.seeds.split(':').join('_') + uri += ':'+this.props.params.seeds.split(':').join('_'); } return ( @@ -218,7 +228,7 @@ class Discover extends React.Component{

Tracks

- {this.props.recommendations.tracks ? : null} +
) @@ -258,9 +268,9 @@ class Discover extends React.Component{ const mapStateToProps = (state, ownProps) => { return { - albums: (state.core.albums ? state.core.albums : []), - artists: (state.core.artists ? state.core.artists : []), - tracks: (state.core.tracks ? state.core.tracks : []), + albums: state.core.albums, + artists: state.core.artists, + tracks: state.core.tracks, genres: (state.core.genres ? state.core.genres : []), authorized: state.spotify.authorization, load_queue: state.ui.load_queue,