Operational, ready for testing

This commit is contained in:
James Barnsley
2017-03-24 23:05:43 +13:00
parent ca91bb019a
commit 8a6ab339af
7 changed files with 160 additions and 55 deletions

View File

@ -43,7 +43,8 @@ class ArtistGrid extends React.Component{
<Thumbnail size="medium" images={artist.images} /> <Thumbnail size="medium" images={artist.images} />
<div className="name">{ artist.name }</div> <div className="name">{ artist.name }</div>
<div className="secondary"> <div className="secondary">
{artist.followers ? artist.followers.total.toLocaleString()+' followers' : <span>0 followers</span>} {artist.followers ? artist.followers.total.toLocaleString()+' followers' : null}
{artist.albums_uris ? artist.albums_uris.length+' albums' : null}
</div> </div>
</Link> </Link>
) )

View File

@ -38,6 +38,14 @@ export default class GridItem extends React.Component{
) )
break break
case 'artist':
return (
<span>
{ item.followers ? item.followers.total.toLocaleString()+' followers' : item.albums_uris.length+' albums' }
</span>
)
break
default: default:
return ( return (
<span> <span>

View File

@ -214,25 +214,47 @@ export function getLibraryAlbums(){
/** /**
* Other general actions * Searching
**/ **/
export function getSearchResults(query, uris = null, fields = ['any']){ export function getTrackSearchResults(query, limit = 100, uri_schemes){
return { return {
type: 'MOPIDY_GET_SEARCH_RESULTS', type: 'MOPIDY_GET_TRACK_SEARCH_RESULTS',
query: query, query: query,
uris: uris, limit: limit,
fields: fields uri_schemes: uri_schemes
} }
} }
export function getArtistSearchResults(query){ export function getArtistSearchResults(query, limit = 100){
return { return {
type: 'MOPIDY_GET_ARTIST_SEARCH_RESULTS', type: 'MOPIDY_GET_ARTIST_SEARCH_RESULTS',
query: query query: query,
limit: limit
} }
} }
export function getAlbumSearchResults(query, limit = 100){
return {
type: 'MOPIDY_GET_ALBUM_SEARCH_RESULTS',
query: query,
limit: limit
}
}
export function getPlaylistSearchResults(query, limit = 100){
return {
type: 'MOPIDY_GET_PLAYLIST_SEARCH_RESULTS',
query: query,
limit: limit
}
}
/**
* Other general actions
**/
export function getQueueHistory(){ export function getQueueHistory(){
return { return {
type: 'MOPIDY_INSTRUCT', type: 'MOPIDY_INSTRUCT',

View File

@ -313,23 +313,13 @@ const MopidyMiddleware = (function(){
**/ **/
case 'MOPIDY_GET_SEARCH_RESULTS': case 'MOPIDY_GET_TRACK_SEARCH_RESULTS':
var queryObject = {}; instruct( socket, store, 'library.search', {query: {any: [action.query]}, uris: action.uri_schemes})
for( var i = 0; i < action.fields.length; i++ ){
queryObject[action.fields[i]] = [action.query];
}
console.log({query: queryObject, uris: action.uris})
instruct( socket, store, 'library.search', {query: queryObject, uris: action.uris})
.then( response => { .then( response => {
console.log(response)
// collate all our different sources into one array // collate all our different sources into one array
var tracks = [] var tracks = []
for( var i = 0; i < response.length; i++ ){ for( var i = 0; i < response.length; i++ ){
if( response[i].tracks ) tracks = [...tracks, ...response[i].tracks] if( response[i].tracks ) tracks = [...tracks, ...response[i].tracks.splice(0,action.limit)]
} }
store.dispatch({ type: 'SEARCH_RESULTS_LOADED', tracks: tracks }); store.dispatch({ type: 'SEARCH_RESULTS_LOADED', tracks: tracks });
@ -337,7 +327,11 @@ const MopidyMiddleware = (function(){
break; break;
case 'MOPIDY_GET_ARTIST_SEARCH_RESULTS': case 'MOPIDY_GET_ARTIST_SEARCH_RESULTS':
instruct( socket, store, 'library.search', {query: {artist: [action.query]}, uris: ['local:','file:','m3u:']})
// backends that provide artist data
var uri_schemes = ['local:','file:','m3u:']
instruct( socket, store, 'library.search', {query: {artist: [action.query]}, uris: uri_schemes})
.then( response => { .then( response => {
// collate all our different sources into one array // collate all our different sources into one array
@ -356,7 +350,9 @@ const MopidyMiddleware = (function(){
} }
} }
} }
artists_uris = helpers.removeDuplicates(artists_uris)
// TODO: limit uris at the loop, rather than post loop for performance
artists_uris = helpers.removeDuplicates(artists_uris).splice(0, action.limit)
// load each artist // load each artist
for (var i = 0; i < artists_uris.length; i++){ for (var i = 0; i < artists_uris.length; i++){
@ -368,6 +364,74 @@ const MopidyMiddleware = (function(){
}) })
break; break;
case 'MOPIDY_GET_ALBUM_SEARCH_RESULTS':
// backends that provide artist data
var uri_schemes = ['local:','file:','m3u:']
instruct( socket, store, 'library.search', {query: {album: [action.query]}, uris: uri_schemes})
.then( response => {
// collate all our different sources into one array
var albums_uris = []
for (var i = 0; i < response.length; i++){
if (response[i].tracks){
for (var j = 0; j < response[i].tracks.length; j++){
if (response[i].tracks[j].album){
var album = response[i].tracks[j].album
if (album.uri){
albums_uris.push(album.uri)
}
}
}
}
}
// TODO: limit uris at the loop, rather than post loop for performance
albums_uris = helpers.removeDuplicates(albums_uris).splice(0, action.limit)
// load each album
for (var i = 0; i < albums_uris.length; i++){
store.dispatch(mopidyActions.getAlbum(albums_uris[i]))
}
// and plug in their URIs
store.dispatch({ type: 'SEARCH_RESULTS_LOADED', albums_uris: albums_uris })
})
break;
case 'MOPIDY_GET_PLAYLIST_SEARCH_RESULTS':
var state = store.getState()
if (state.ui.search_settings){
var uri_schemes = state.ui.search_settings.uri_schemes
} else {
var uri_schemes = state.mopidy.uri_schemes
}
instruct( socket, store, 'playlists.asList')
.then( response => {
var playlists_uris = []
for (var i = 0; i < response.length; i++){
var playlist = response[i]
if (playlist.name.includes(action.query) && uri_schemes.indexOf(helpers.uriSource(playlist.uri)+':') > -1){
playlists_uris.push(playlist.uri)
}
}
playlists_uris = playlists_uris.splice(0, action.limit)
// load each playlist
for (var i = 0; i < playlists_uris.length; i++){
store.dispatch(mopidyActions.getPlaylist(playlists_uris[i]))
}
// and plug in their URIs
store.dispatch({ type: 'SEARCH_RESULTS_LOADED', playlists_uris: playlists_uris })
})
break;
/** /**
* =============================================================== PLAYLIST(S) ========== * =============================================================== PLAYLIST(S) ==========
@ -758,11 +822,10 @@ const MopidyMiddleware = (function(){
} }
} }
if (albums){ if (albums){
console.log(albums) store.dispatch({
/*store.dispatch({
type: 'ALBUMS_LOADED', type: 'ALBUMS_LOADED',
albums: albums albums: albums
})*/ })
} }
var artist = Object.assign( var artist = Object.assign(

View File

@ -113,7 +113,13 @@ const UIMiddleware = (function(){
case 'SEARCH_STARTED': case 'SEARCH_STARTED':
ReactGA.event({ category: 'Search', action: 'Started', label: action.type+': '+action.query }) ReactGA.event({ category: 'Search', action: 'Started', label: action.type+': '+action.query })
var state = store.getState() var state = store.getState()
if (state.ui.search_settings){
var uri_schemes = state.ui.search_settings.uri_schemes
} else {
var uri_schemes = state.mopidy.uri_schemes
}
// initiate spotify searching // initiate spotify searching
if (!action.only_mopidy){ if (!action.only_mopidy){
@ -124,24 +130,6 @@ const UIMiddleware = (function(){
// backend searching (mopidy) // backend searching (mopidy)
if (state.mopidy.connected){ if (state.mopidy.connected){
if (state.ui.search_settings){
var uri_schemes = state.ui.search_settings.uri_schemes
} else {
var uri_schemes = state.mopidy.uri_schemes
}
uri_schemes.sort()
// put local backends first as they'll always be fastest
var local_backends = ['local:','m3u:','file:']
for (var i = 0; i < local_backends.length; i++){
var index = uri_schemes.indexOf(local_backends[i])
if (index > -1){
uri_schemes.splice(index,1)
uri_schemes.unshift(local_backends[i])
}
}
switch (action.search_type){ switch (action.search_type){
case 'playlists': case 'playlists':
store.dispatch(mopidyActions.getPlaylistSearchResults(action.query)) store.dispatch(mopidyActions.getPlaylistSearchResults(action.query))
@ -155,11 +143,21 @@ const UIMiddleware = (function(){
store.dispatch(mopidyActions.getAlbumSearchResults(action.query)) store.dispatch(mopidyActions.getAlbumSearchResults(action.query))
break break
case 'tracks':
for (var i = 0; i < uri_schemes.length; i++){
store.dispatch(mopidyActions.getTrackSearchResults(action.query,100,[uri_schemes[i]]))
}
break
default: default:
store.dispatch(mopidyActions.getPlaylistSearchResults(action.query,6))
store.dispatch(mopidyActions.getArtistSearchResults(action.query,6))
store.dispatch(mopidyActions.getAlbumSearchResults(action.query,6))
// wrap each uri scheme in it's own search request // wrap each uri scheme in it's own search request
// this means slow backends won't hold up the whole request // this means slow backends won't hold up the whole request
for (var i = 0; i < uri_schemes.length; i++){ for (var i = 0; i < uri_schemes.length; i++){
store.dispatch(mopidyActions.getSearchResults(action.query, [uri_schemes[i]], ['any'])) store.dispatch(mopidyActions.getTrackSearchResults(action.query,100,[uri_schemes[i]]))
} }
} }
} }

View File

@ -31,13 +31,12 @@ class Search extends React.Component{
componentWillReceiveProps(newProps){ componentWillReceiveProps(newProps){
// new query if (this.props.params.query != newProps.params.query || this.props.params.type != newProps.params.type){
if( this.props.params.query != newProps.params.query ){
this.props.uiActions.startSearch(newProps.params.type, newProps.params.query) this.props.uiActions.startSearch(newProps.params.type, newProps.params.query)
} }
// mopidy comes online // mopidy comes online
if( !this.props.mopidy_connected && newProps.mopidy_connected ){ if (!this.props.mopidy_connected && newProps.mopidy_connected){
this.props.uiActions.startSearch(newProps.params.type, newProps.params.query, true) this.props.uiActions.startSearch(newProps.params.type, newProps.params.query, true)
} }
} }
@ -47,6 +46,8 @@ class Search extends React.Component{
} }
renderResults(){ renderResults(){
var spotify_search_enabled = (this.props.search_settings && this.props.search_settings.spotify)
var artists = [] var artists = []
if (this.props.artists_uris){ if (this.props.artists_uris){
for (var i = 0; i < this.props.artists_uris.length; i++){ for (var i = 0; i < this.props.artists_uris.length; i++){
@ -93,7 +94,7 @@ class Search extends React.Component{
<div> <div>
<section className="grid-wrapper"> <section className="grid-wrapper">
<ArtistGrid artists={artists} /> <ArtistGrid artists={artists} />
<LazyLoadListener enabled={this.props['artists_more'] && this.props.search_settings.spotify} loadMore={ () => this.loadMore('artists') }/> <LazyLoadListener enabled={this.props['artists_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('artists') }/>
</section> </section>
</div> </div>
) )
@ -104,7 +105,7 @@ class Search extends React.Component{
<div> <div>
<section className="grid-wrapper"> <section className="grid-wrapper">
<AlbumGrid albums={albums} /> <AlbumGrid albums={albums} />
<LazyLoadListener enabled={this.props['albums_more'] && this.props.search_settings.spotify} loadMore={ () => this.loadMore('albums') }/> <LazyLoadListener enabled={this.props['albums_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('albums') }/>
</section> </section>
</div> </div>
) )
@ -115,7 +116,7 @@ class Search extends React.Component{
<div> <div>
<section className="grid-wrapper"> <section className="grid-wrapper">
<PlaylistGrid playlists={playlists} /> <PlaylistGrid playlists={playlists} />
<LazyLoadListener enabled={this.props['playlists_more'] && this.props.search_settings.spotify} loadMore={ () => this.loadMore('playlists') }/> <LazyLoadListener enabled={this.props['playlists_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('playlists') }/>
</section> </section>
</div> </div>
) )
@ -126,7 +127,7 @@ class Search extends React.Component{
<div> <div>
<section className="list-wrapper"> <section className="list-wrapper">
<TrackList show_source_icon={true} tracks={ tracks } /> <TrackList show_source_icon={true} tracks={ tracks } />
<LazyLoadListener enabled={this.props['tracks_more'] && this.props.search_settings.spotify} loadMore={ () => this.loadMore('tracks') }/> <LazyLoadListener enabled={this.props['tracks_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('tracks') }/>
</section> </section>
</div> </div>
) )
@ -159,7 +160,7 @@ class Search extends React.Component{
<section className="list-wrapper"> <section className="list-wrapper">
<h4 className="left-padding"><Link to={global.baseURL+'search/'+this.props.params.query+'/tracks'}>Tracks</Link></h4> <h4 className="left-padding"><Link to={global.baseURL+'search/'+this.props.params.query+'/tracks'}>Tracks</Link></h4>
<TrackList show_source_icon={true} tracks={ tracks } /> <TrackList show_source_icon={true} tracks={ tracks } />
<LazyLoadListener enabled={this.props['tracks_more'] && this.props.search_settings.spotify} loadMore={ () => this.loadMore('tracks') }/> <LazyLoadListener enabled={this.props['tracks_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('tracks') }/>
</section> </section>
</div> </div>

View File

@ -129,6 +129,18 @@
} }
} }
&.library-local-album-list .list-item{
.col {
&.name,
&.artists {
width: 45%;
}
&.tracks_total {
width: 10%;
}
}
}
&.artist-list .list-item { &.artist-list .list-item {
.col { .col {
&.name { &.name {