Operational, ready for testing
This commit is contained in:
@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
@ -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++ ){
|
.then( response => {
|
||||||
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 => {
|
|
||||||
|
|
||||||
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(
|
||||||
|
|||||||
@ -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]]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user