Lazy loader; Filter on album library

This commit is contained in:
James Barnsley
2017-08-07 21:34:33 +12:00
parent 97ba83a06d
commit ba97a6be4a
23 changed files with 118 additions and 77 deletions

View File

@ -6,7 +6,9 @@ export default class LazyLoadListener extends React.Component{
constructor(props) {
super(props);
this.state = { loading: false }
this.state = {
loading: false
}
this.handleScroll = this.handleScroll.bind(this);
}
@ -20,7 +22,7 @@ export default class LazyLoadListener extends React.Component{
handleScroll(e){
if( (window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 80) ){
if( !this.state.loading && this.props.enabled ){
if (!this.state.loading && this.props.loading){
this.setState({ loading: true })
this.props.loadMore();
}
@ -31,7 +33,7 @@ export default class LazyLoadListener extends React.Component{
render(){
return (
<div className="lazy-loader body-loader">
<div className={"lazy-loader body-loader"+(this.state.loading ? ' loading' : '')}>
{this.state.loading ? <div className="loader"></div> : null}
</div>
)

View File

@ -13,7 +13,7 @@ export default class AddToPlaylistModal extends React.Component{
}
playlistSelected( playlist_uri ){
this.props.uiActions.addTracksToPlaylist( playlist_uri, this.props.tracks_uris )
this.props.coreActions.addTracksToPlaylist( playlist_uri, this.props.tracks_uris )
this.props.uiActions.closeModal()
}

View File

@ -24,7 +24,7 @@ export default class CreatePlaylistModal extends React.Component{
this.setState({error: 'Name is required'})
return false
} else {
this.props.uiActions.createPlaylist( this.state.scheme, this.state.name, this.state.description, this.state.is_public, this.state.is_collaborative )
this.props.coreActions.createPlaylist( this.state.scheme, this.state.name, this.state.description, this.state.is_public, this.state.is_collaborative )
this.props.uiActions.closeModal()
}

View File

@ -24,7 +24,7 @@ export default class EditPlaylistModal extends React.Component{
this.setState({error: 'Name is required'})
return false
} else {
this.props.uiActions.savePlaylist(this.props.data.uri, this.state.name, this.state.description, this.state.is_public, this.state.is_collaborative)
this.props.coreActions.savePlaylist(this.props.data.uri, this.state.name, this.state.description, this.state.is_public, this.state.is_collaborative)
this.props.uiActions.closeModal()
return false
}

View File

@ -47,10 +47,10 @@ class Modal extends React.Component{
</div>
<div className="content">
{ this.props.modal.name == 'add_to_playlist' ? <AddToPlaylistModal uiActions={this.props.uiActions} playlists={this.props.playlists} tracks_uris={this.props.modal.data.tracks_uris} /> : null }
{ this.props.modal.name == 'add_to_playlist' ? <AddToPlaylistModal uiActions={this.props.uiActions} coreActions={this.props.coreActions} playlists={this.props.playlists} tracks_uris={this.props.modal.data.tracks_uris} /> : null }
{ this.props.modal.name == 'add_to_queue' ? <AddToQueueModal uiActions={this.props.uiActions} mopidyActions={this.props.mopidyActions} /> : null }
{ this.props.modal.name == 'create_playlist' ? <CreatePlaylistModal uiActions={this.props.uiActions} /> : null }
{ this.props.modal.name == 'edit_playlist' ? <EditPlaylistModal uiActions={this.props.uiActions} data={this.props.modal.data} /> : null }
{ this.props.modal.name == 'create_playlist' ? <CreatePlaylistModal uiActions={this.props.uiActions} coreActions={this.props.coreActions} /> : null }
{ this.props.modal.name == 'edit_playlist' ? <EditPlaylistModal uiActions={this.props.uiActions} coreActions={this.props.coreActions} data={this.props.modal.data} /> : null }
{ this.props.modal.name == 'send_authorization' ? <AuthorizationModal_Send uiActions={this.props.uiActions} pusherActions={this.props.pusherActions} data={this.props.modal.data} /> : null }
{ this.props.modal.name == 'receive_authorization' ? <AuthorizationModal_Receive uiActions={this.props.uiActions} spotifyActions={this.props.spotifyActions} data={this.props.modal.data} /> : null }
{ this.props.modal.name == 'edit_radio' ? <EditRadioModal uiActions={this.props.uiActions} pusherActions={this.props.pusherActions} spotifyActions={this.props.spotifyActions} data={this.props.modal.data} radio={this.props.radio} artists={this.props.artists} tracks={this.props.tracks} /> : null }

View File

@ -866,7 +866,7 @@ const MopidyMiddleware = (function(){
var album = Object.assign(
{},
{
is_mopidy: true,
source: 'local',
artists: response[uri][0].artists,
tracks: response[uri],
tracks_total: response[uri].length
@ -895,7 +895,7 @@ const MopidyMiddleware = (function(){
{ images: [] },
response[0].album,
{
is_mopidy: true,
source: 'local',
artists: response[0].artists,
tracks: response,
tracks_total: response.length

View File

@ -250,6 +250,7 @@ const SpotifyMiddleware = (function(){
{},
action.data.artists.items[i],
{
source: 'spotify',
in_library: true // assumed because we asked for library items
}
)
@ -276,6 +277,7 @@ const SpotifyMiddleware = (function(){
action.data.items[i].album,
{
in_library: true, // assumed because we asked for library items
source: 'spotify',
added_at: action.data.items[i].added_at,
tracks: action.data.items[i].album.tracks.items,
tracks_more: action.data.items[i].album.tracks.next,

View File

@ -98,7 +98,7 @@ class Album extends React.Component{
render(){
if (helpers.isLoading(this.props.load_queue,['spotify_albums/'+helpers.getFromUri('albumid',this.props.params.uri)])){
return (
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
)

View File

@ -98,7 +98,7 @@ class Artist extends React.Component{
renderBody(){
if (helpers.isLoading(this.props.load_queue,['spotify_artists/'+helpers.getFromUri('artistid',this.props.params.uri), 'lastfm_method=artist.getInfo'])){
return (
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
)

View File

@ -159,7 +159,7 @@ class Playlist extends React.Component{
if (helpers.isLoading(this.props.load_queue,['spotify_users/'+user_id+'/playlists/'+playlist_id+'?'])){
return (
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
)

View File

@ -23,7 +23,7 @@ class DiscoverCategories extends React.Component{
return (
<div className="view discover-categories-view">
<Header icon="grid" title="Genre / Mood" />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -38,7 +38,7 @@ class DiscoverCategory extends React.Component{
return (
<div className="view discover-categories-view">
<Header icon="grid" title={(this.props.category ? this.props.category.name : 'Category')} />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -74,7 +74,7 @@ class DiscoverFeatured extends React.Component{
return (
<div className="view discover-featured-view">
<Header icon="star" title="Featured playlists" />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -82,7 +82,7 @@ class DiscoverNewReleases extends React.Component{
return (
<div className="view discover-new-releases-view">
<Header icon="leaf" title="New Releases" />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -174,7 +174,7 @@ class Discover extends React.Component{
renderResults(){
if (helpers.isLoading(this.props.load_queue,['spotify_recommendations'])){
return (
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
)

View File

@ -108,28 +108,26 @@ class LibraryAlbums extends React.Component{
label: 'Added',
name: 'added_at'
},
{
label: 'Released',
name: 'release_date'
},
{
label: 'Tracks',
name: 'tracks_total'
},
{
label: 'Source',
name: 'source'
}
]
return (
<section className="content-wrapper">
<List
handleContextMenu={(e,item) => this.handleContextMenu(e,item)}
rows={albums}
columns={columns}
className="album-list"
link_prefix={global.baseURL+"album/"} />
</section>
<List
handleContextMenu={(e,item) => this.handleContextMenu(e,item)}
rows={albums}
columns={columns}
className="album-list"
link_prefix={global.baseURL+"album/"} />
)
}else if( this.props.view == 'detail' ){
return (
<section className="content-wrapper albums-detail-subview">
<div>
{
albums.map( album => {
return (
@ -150,38 +148,42 @@ class LibraryAlbums extends React.Component{
)
})
}
</section>
</div>
)
}else{
return (
<section className="content-wrapper">
<AlbumGrid
handleContextMenu={(e,item) => this.handleContextMenu(e,item)}
albums={albums} />
</section>
<AlbumGrid
handleContextMenu={(e,item) => this.handleContextMenu(e,item)}
albums={albums} />
)
}
}
render(){
if (helpers.isLoading(this.props.load_queue,['spotify_me/albums'])){
return (
<div className="view library-albums-view">
<Header icon="cd" title="My albums" />
<div className="body-loader">
<div className="loader"></div>
</div>
</div>
)
}
var albums = []
if (this.props.library_albums && this.props.albums){
for (var i = 0; i < this.props.library_albums.length; i++){
var uri = this.props.library_albums[i]
if (this.props.albums.hasOwnProperty(uri)){
albums.push(this.props.albums[uri])
switch (this.props.filter){
case 'spotify':
if (this.props.albums[uri].source == 'spotify'){
albums.push(this.props.albums[uri])
}
break
case 'local':
if (this.props.albums[uri].source == 'local'){
albums.push(this.props.albums[uri])
}
break
default:
albums.push(this.props.albums[uri])
break
}
}
}
@ -190,6 +192,21 @@ class LibraryAlbums extends React.Component{
}
}
var filter_options = [
{
value: 'all',
label: 'All'
},
{
value: 'local',
label: 'Local'
},
{
value: 'spotify',
label: 'Spotify'
}
]
var view_options = [
{
value: 'thumbnails',
@ -214,18 +231,19 @@ class LibraryAlbums extends React.Component{
value: 'added_at',
label: 'Added'
},
{
value: 'release_date',
label: 'Released'
},
{
value: 'tracks_total',
label: 'Tracks'
},
{
value: 'source',
label: 'Source'
}
]
var options = (
<span>
<DropdownField icon="filter" name="Filter" value={this.props.filter} options={filter_options} handleChange={val => {this.props.uiActions.set({ library_albums_filter: val}); this.props.uiActions.hideContextMenu() }} />
<DropdownField icon="sort" name="Sort" value={this.props.sort} options={sort_options} reverse={this.props.sort_reverse} handleChange={val => {this.setSort(val); this.props.uiActions.hideContextMenu() }} />
<DropdownField icon="eye" name="View" value={this.props.view} options={view_options} handleChange={val => {this.props.uiActions.set({ library_albums_view: val }); this.props.uiActions.hideContextMenu() }} />
</span>
@ -233,10 +251,15 @@ class LibraryAlbums extends React.Component{
return (
<div className="view library-albums-view">
<Header icon="cd" title="My albums" options={options} uiActions={this.props.uiActions} />
{ this.renderView(albums) }
<LazyLoadListener enabled={this.props.library_albums_spotify_more} loadMore={() => this.loadMoreSpotify()}/>
<LazyLoadListener enabled={this.moreURIsToLoad().length > 0} loadMore={() => this.loadMoreMopidy()}/>
<section className="content-wrapper">
{ this.renderView(albums) }
<LazyLoadListener loading={this.props.library_albums_spotify_more} loadMore={() => this.loadMoreSpotify()}/>
<LazyLoadListener loading={this.moreURIsToLoad().length > 0} loadMore={() => this.loadMoreMopidy()}/>
</section>
</div>
);
}
@ -259,6 +282,7 @@ const mapStateToProps = (state, ownProps) => {
library_albums_spotify_started: state.core.library_albums_spotify_started,
library_albums_spotify_more: state.core.library_albums_spotify_more,
view: state.ui.library_albums_view,
filter: (state.ui.library_albums_filter ? state.ui.library_albums_filter : 'all'),
sort: (state.ui.library_albums_sort ? state.ui.library_albums_sort : 'name'),
sort_reverse: (state.ui.library_albums_sort_reverse ? true : false)
}

View File

@ -117,7 +117,7 @@ class LibraryBrowse extends React.Component{
return (
<div className="view library-local-view">
<Header icon="music" title={title} options={options} uiActions={this.props.uiActions} />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -156,7 +156,7 @@ class LibraryLocalAlbums extends React.Component{
return (
<div className="view library-local-view">
<Header icon="music" title="Local albums" options={options} uiActions={this.props.uiActions} />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -59,7 +59,7 @@ class LibraryLocalArtists extends React.Component{
return (
<div className="view library-local-view">
<Header icon="music" title="Local artists" />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -45,7 +45,7 @@ class LibraryPlaylists extends React.Component{
renderView(){
if (helpers.isLoading(this.props.load_queue,['spotify_me/playlists'])){
return (
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
)
@ -109,10 +109,6 @@ class LibraryPlaylists extends React.Component{
label: 'Owner',
name: 'owner'
},
{
label: 'Source',
name: 'source'
},
{
label: 'Tracks',
name: 'tracks_total'
@ -120,12 +116,14 @@ class LibraryPlaylists extends React.Component{
{
label: 'Editable',
name: 'can_edit'
},
{
label: 'Source',
name: 'source'
}
]
}
console.log(columns)
return (
<section className="content-wrapper">
<List

View File

@ -32,7 +32,7 @@ class LibraryTracks extends React.Component{
return (
<div className="view library-tracks-view">
<Header icon="music" title="My tracks" />
<div className="body-loader">
<div className="body-loader loading">
<div className="loader"></div>
</div>
</div>

View File

@ -52,13 +52,6 @@
padding-bottom: 2px;
}
.source {
color: $mid_grey;
position: absolute;
top: 14px;
right: 12px;
}
&.field {
padding: 0 !important;
@ -92,6 +85,13 @@
margin-top: -3px;
background: transparent;
}
.source {
color: $mid_grey;
position: absolute;
top: 14px;
right: 12px;
}
}
}

View File

@ -2,11 +2,18 @@
.body-loader {
padding: 35vh 0;
&.loading {
.loader {
opacity: 1;
}
}
.loader {
height: 120px;
width: 120px;
margin: 0 auto;
position: relative;
opacity: 0;
&:before,
&:after {
@ -42,11 +49,19 @@
}
&.lazy-loader {
padding: 0;
padding: 20px;
height: 40px;
.loader {
height: 40px;
width: 40px;
opacity: 0;
}
&.loading {
.loader {
opacity: 1;
}
}
}
}