Upgrading process calls; Tracks library now works like aother asset libraries (huge libraries may kill react-persist?)
This commit is contained in:
@ -20,10 +20,15 @@ import { i18n, I18n } from '../../locale';
|
||||
import Loader from '../../components/Loader';
|
||||
import {
|
||||
makeLibrarySelector,
|
||||
makeLoadingSelector,
|
||||
makeProcessProgressSelector,
|
||||
} from '../../util/selectors';
|
||||
|
||||
const processKeys = [
|
||||
'MOPIDY_GET_LIBRARY_ALBUMS',
|
||||
'SPOTIFY_GET_LIBRARY_ALBUMS',
|
||||
'GOOGLE_GET_LIBRARY_ALBUMS',
|
||||
];
|
||||
|
||||
class LibraryAlbums extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -68,7 +73,7 @@ class LibraryAlbums extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onRefresh = () => {
|
||||
refresh = () => {
|
||||
const { uiActions: { hideContextMenu } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
@ -77,6 +82,13 @@ class LibraryAlbums extends React.Component {
|
||||
this.getSpotifyLibrary(true);
|
||||
}
|
||||
|
||||
cancelRefresh = () => {
|
||||
const { uiActions: { hideContextMenu, cancelProcess } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
cancelProcess(processKeys);
|
||||
}
|
||||
|
||||
getMopidyLibrary = (forceRefetch = false) => {
|
||||
const {
|
||||
source,
|
||||
@ -175,7 +187,6 @@ class LibraryAlbums extends React.Component {
|
||||
sort,
|
||||
sort_reverse,
|
||||
view,
|
||||
loading,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const {
|
||||
@ -184,9 +195,8 @@ class LibraryAlbums extends React.Component {
|
||||
} = this.state;
|
||||
let { albums } = this.props;
|
||||
|
||||
if (loading) {
|
||||
console.log(loading_progress);
|
||||
return <Loader body loading progress={loading_progress} />
|
||||
if (loading_progress < 1) {
|
||||
return <Loader body loading progress={loading_progress} />;
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
@ -245,11 +255,13 @@ class LibraryAlbums extends React.Component {
|
||||
source,
|
||||
sort_reverse,
|
||||
uiActions,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const {
|
||||
filter,
|
||||
per_page,
|
||||
} = this.state;
|
||||
const loading = loading_progress < 1;
|
||||
|
||||
const source_options = [
|
||||
{
|
||||
@ -349,11 +361,11 @@ class LibraryAlbums extends React.Component {
|
||||
<Button
|
||||
noHover
|
||||
discrete
|
||||
onClick={this.onRefresh}
|
||||
onClick={loading ? this.cancelRefresh : this.refresh}
|
||||
tracking={{ category: 'LibraryAlbums', action: 'Refresh' }}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
<I18n path="actions.refresh" />
|
||||
{loading ? <Icon name="close" /> : <Icon name="refresh" /> }
|
||||
{loading ? <I18n path="actions.cancel" /> : <I18n path="actions.refresh" /> }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
@ -372,21 +384,15 @@ class LibraryAlbums extends React.Component {
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const source = state.ui.library_albums_source ? state.ui.library_albums_source : 'all';
|
||||
const loadingSelector = makeLoadingSelector(['(.*):library:albums']);
|
||||
|
||||
const libraryUris = [];
|
||||
if (source === 'all' || source === 'local') libraryUris.push('mopidy:library:albums');
|
||||
if (source === 'all' || source === 'spotify') libraryUris.push('spotify:library:albums');
|
||||
if (source === 'all' || source === 'google') libraryUris.push('google:library:albums');
|
||||
const librarySelector = makeLibrarySelector(libraryUris);
|
||||
const processProgressSelector = makeProcessProgressSelector([
|
||||
'MOPIDY_GET_LIBRARY_ALBUMS',
|
||||
'SPOTIFY_GET_LIBRARY_ALBUMS',
|
||||
'GOOGLE_GET_LIBRARY_ALBUMS',
|
||||
]);
|
||||
const processProgressSelector = makeProcessProgressSelector(processKeys);
|
||||
|
||||
return {
|
||||
loading: loadingSelector(state),
|
||||
loading_progress: processProgressSelector(state),
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
albums: librarySelector(state),
|
||||
|
||||
@ -21,6 +21,12 @@ import {
|
||||
makeProcessProgressSelector,
|
||||
} from '../../util/selectors';
|
||||
|
||||
const processKeys = [
|
||||
'MOPIDY_GET_LIBRARY_ARTISTS',
|
||||
'SPOTIFY_GET_LIBRARY_ARTISTS',
|
||||
'GOOGLE_GET_LIBRARY_ARTISTS',
|
||||
];
|
||||
|
||||
class LibraryArtists extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -63,7 +69,7 @@ class LibraryArtists extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onRefresh = () => {
|
||||
refresh = () => {
|
||||
const { uiActions: { hideContextMenu } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
@ -72,6 +78,13 @@ class LibraryArtists extends React.Component {
|
||||
this.getSpotifyLibrary(true);
|
||||
}
|
||||
|
||||
cancelRefresh = () => {
|
||||
const { uiActions: { hideContextMenu, cancelProcess } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
cancelProcess(processKeys);
|
||||
}
|
||||
|
||||
setSort = (value) => {
|
||||
const { sort, sort_reverse, uiActions: { set } } = this.props;
|
||||
let reverse = false;
|
||||
@ -151,7 +164,6 @@ class LibraryArtists extends React.Component {
|
||||
sort,
|
||||
sort_reverse,
|
||||
view,
|
||||
loading,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const {
|
||||
@ -160,7 +172,7 @@ class LibraryArtists extends React.Component {
|
||||
} = this.state;
|
||||
let { artists } = this.props;
|
||||
|
||||
if (loading) {
|
||||
if (loading_progress < 1) {
|
||||
return <Loader body loading progress={loading_progress} />
|
||||
}
|
||||
|
||||
@ -215,7 +227,9 @@ class LibraryArtists extends React.Component {
|
||||
const {
|
||||
spotify_available,
|
||||
google_available,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const loading = loading_progress < 1;
|
||||
|
||||
const source_options = [
|
||||
{
|
||||
@ -307,11 +321,11 @@ class LibraryArtists extends React.Component {
|
||||
<Button
|
||||
noHover
|
||||
discrete
|
||||
onClick={this.onRefresh}
|
||||
onClick={loading ? this.cancelRefresh : this.refresh}
|
||||
tracking={{ category: 'LibraryArtists', action: 'Refresh' }}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
<I18n path="actions.refresh" />
|
||||
{loading ? <Icon name="close" /> : <Icon name="refresh" /> }
|
||||
{loading ? <I18n path="actions.cancel" /> : <I18n path="actions.refresh" /> }
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
@ -330,18 +344,13 @@ class LibraryArtists extends React.Component {
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const source = state.ui.library_artists_source || 'all';
|
||||
const loadingSelector = makeLoadingSelector(['(.*):library:artists']);
|
||||
|
||||
const libraryUris = [];
|
||||
if (source === 'all' || source === 'local') libraryUris.push('mopidy:library:artists');
|
||||
if (source === 'all' || source === 'spotify') libraryUris.push('spotify:library:artists');
|
||||
if (source === 'all' || source === 'google') libraryUris.push('google:library:artists');
|
||||
const librarySelector = makeLibrarySelector(libraryUris);
|
||||
const processProgressSelector = makeProcessProgressSelector([
|
||||
'MOPIDY_GET_LIBRARY_ARTISTS',
|
||||
'SPOTIFY_GET_LIBRARY_ARTISTS',
|
||||
'GOOGLE_GET_LIBRARY_ARTISTS',
|
||||
]);
|
||||
const processProgressSelector = makeProcessProgressSelector(processKeys);
|
||||
|
||||
return {
|
||||
loading_progress: processProgressSelector(state),
|
||||
@ -349,7 +358,6 @@ const mapStateToProps = (state) => {
|
||||
google_available: (state.mopidy.uri_schemes && state.mopidy.uri_schemes.includes('gmusic:')),
|
||||
spotify_available: (state.spotify.access_token),
|
||||
artists: librarySelector(state),
|
||||
loading: loadingSelector(state),
|
||||
source,
|
||||
sort: (state.ui.library_artists_sort ? state.ui.library_artists_sort : null),
|
||||
sort_reverse: (state.ui.library_artists_sort_reverse ? state.ui.library_artists_sort_reverse : false),
|
||||
|
||||
@ -16,10 +16,17 @@ import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
import { applyFilter, removeDuplicates, sortItems } from '../../util/arrays';
|
||||
import { I18n, i18n } from '../../locale';
|
||||
import { collate } from '../../util/format';
|
||||
import { isLoading } from '../../util/helpers';
|
||||
import Loader from '../../components/Loader';
|
||||
import { makeLibrarySelector, makeLoadingSelector } from '../../util/selectors';
|
||||
import {
|
||||
makeLibrarySelector,
|
||||
makeLoadingSelector,
|
||||
makeProcessProgressSelector,
|
||||
} from '../../util/selectors';
|
||||
|
||||
const processKeys = [
|
||||
'MOPIDY_GET_LIBRARY_PLAYLISTS',
|
||||
'SPOTIFY_GET_LIBRARY_PLAYLISTS',
|
||||
];
|
||||
|
||||
class LibraryPlaylists extends React.Component {
|
||||
constructor(props) {
|
||||
@ -55,7 +62,7 @@ class LibraryPlaylists extends React.Component {
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
|
||||
onRefresh = () => {
|
||||
refresh = () => {
|
||||
const { uiActions: { hideContextMenu } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
@ -63,6 +70,13 @@ class LibraryPlaylists extends React.Component {
|
||||
this.getSpotifyLibrary(true);
|
||||
}
|
||||
|
||||
cancelRefresh = () => {
|
||||
const { uiActions: { hideContextMenu, cancelProcess } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
cancelProcess(processKeys);
|
||||
}
|
||||
|
||||
getMopidyLibrary = (forceRefetch = false) => {
|
||||
const {
|
||||
source,
|
||||
@ -137,7 +151,7 @@ class LibraryPlaylists extends React.Component {
|
||||
sort,
|
||||
sort_reverse,
|
||||
view,
|
||||
loading,
|
||||
loading_progress,
|
||||
playlists: playlistsProp,
|
||||
} = this.props;
|
||||
const {
|
||||
@ -145,8 +159,8 @@ class LibraryPlaylists extends React.Component {
|
||||
limit,
|
||||
} = this.state;
|
||||
|
||||
if (loading) {
|
||||
return <Loader body loading />;
|
||||
if (loading_progress < 1) {
|
||||
return <Loader body loading progress={loading_progress} />;
|
||||
}
|
||||
let playlists = [...playlistsProp];
|
||||
|
||||
@ -206,10 +220,12 @@ class LibraryPlaylists extends React.Component {
|
||||
sort,
|
||||
sort_reverse,
|
||||
view,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const {
|
||||
filter,
|
||||
} = this.state;
|
||||
const loading = loading_progress < 1;
|
||||
|
||||
const source_options = [
|
||||
{
|
||||
@ -306,11 +322,11 @@ class LibraryPlaylists extends React.Component {
|
||||
<Button
|
||||
noHover
|
||||
discrete
|
||||
onClick={this.onRefresh}
|
||||
onClick={loading ? this.cancelRefresh : this.refresh}
|
||||
tracking={{ category: 'LibraryAlbums', action: 'Refresh' }}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
<I18n path="actions.refresh" />
|
||||
{loading ? <Icon name="close" /> : <Icon name="refresh" /> }
|
||||
{loading ? <I18n path="actions.cancel" /> : <I18n path="actions.refresh" /> }
|
||||
</Button>
|
||||
<Button
|
||||
to="/playlist/create"
|
||||
@ -338,20 +354,20 @@ class LibraryPlaylists extends React.Component {
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const source = state.ui.library_playlists_source || 'all';
|
||||
const loadingSelector = makeLoadingSelector(['(.*):library:playlists']);
|
||||
|
||||
const libraryUris = [];
|
||||
if (source === 'all' || source === 'local') libraryUris.push('mopidy:library:playlists');
|
||||
if (source === 'all' || source === 'spotify') libraryUris.push('spotify:library:playlists');
|
||||
if (source === 'all' || source === 'google') libraryUris.push('google:library:playlists');
|
||||
const librarySelector = makeLibrarySelector(libraryUris);
|
||||
const processProgressSelector = makeProcessProgressSelector(processKeys);
|
||||
|
||||
return {
|
||||
slim_mode: state.ui.slim_mode,
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
spotify_available: state.spotify.access_token,
|
||||
playlists: librarySelector(state),
|
||||
loading: loadingSelector(state),
|
||||
loading_progress: processProgressSelector(state),
|
||||
source,
|
||||
me_id: (state.spotify.me ? state.spotify.me.id : false),
|
||||
view: state.ui.library_playlists_view,
|
||||
|
||||
@ -2,116 +2,336 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import Loader from '../../components/Loader';
|
||||
import TrackList from '../../components/TrackList';
|
||||
import Header from '../../components/Header';
|
||||
import DropdownField from '../../components/Fields/DropdownField';
|
||||
import FilterField from '../../components/Fields/FilterField';
|
||||
import LazyLoadListener from '../../components/LazyLoadListener';
|
||||
import Icon from '../../components/Icon';
|
||||
import * as coreActions from '../../services/core/actions';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
import { isLoading } from '../../util/helpers';
|
||||
import { I18n, i18n } from '../../locale';
|
||||
import { sortItems, applyFilter } from '../../util/arrays';
|
||||
import Button from '../../components/Button';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Loader from '../../components/Loader';
|
||||
import {
|
||||
makeLibrarySelector,
|
||||
makeProcessProgressSelector,
|
||||
} from '../../util/selectors';
|
||||
|
||||
const processKeys = [
|
||||
'MOPIDY_GET_LIBRARY_TRACKS',
|
||||
'SPOTIFY_GET_LIBRARY_TRACKS',
|
||||
];
|
||||
|
||||
class LibraryTracks extends React.Component {
|
||||
componentDidMount() {
|
||||
this.props.uiActions.setWindowTitle(i18n('library.tracks.title'));
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
if (!this.props.spotify_available) {
|
||||
this.props.uiActions.createNotification({
|
||||
level: 'warning',
|
||||
content: i18n('errors.enable_first', { provider: i18n('services.spotify.title') }),
|
||||
this.state = {
|
||||
filter: '',
|
||||
limit: 50,
|
||||
per_page: 50,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
location: {
|
||||
state = {},
|
||||
},
|
||||
uiActions: {
|
||||
setWindowTitle,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
// Restore any limit defined in our location state
|
||||
if (state.limit) {
|
||||
this.setState({
|
||||
limit: state.limit,
|
||||
});
|
||||
} else if (this.props.library_tracks === undefined) {
|
||||
this.props.spotifyActions.getLibraryTracks();
|
||||
}
|
||||
|
||||
setWindowTitle(i18n('library.tracks.title'));
|
||||
this.getMopidyLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
|
||||
componentDidUpdate = ({ source: prevSource }) => {
|
||||
const { source } = this.props;
|
||||
|
||||
if (source !== prevSource) {
|
||||
this.getMopidyLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
loadMore() {
|
||||
this.props.spotifyActions.getMore(
|
||||
this.props.library_tracks_more,
|
||||
null,
|
||||
{
|
||||
type: 'SPOTIFY_LIBRARY_TRACKS_LOADED_MORE',
|
||||
refresh = () => {
|
||||
const { uiActions: { hideContextMenu } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
this.getMopidyLibrary(true);
|
||||
this.getSpotifyLibrary(true);
|
||||
}
|
||||
|
||||
cancelRefresh = () => {
|
||||
const { uiActions: { hideContextMenu, cancelProcess } } = this.props;
|
||||
|
||||
hideContextMenu();
|
||||
cancelProcess(processKeys);
|
||||
}
|
||||
|
||||
getMopidyLibrary = (forceRefetch = false) => {
|
||||
const {
|
||||
source,
|
||||
coreActions: {
|
||||
loadLibrary,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (source !== 'local' && source !== 'all') return;
|
||||
|
||||
loadLibrary('mopidy:library:tracks', { forceRefetch });
|
||||
};
|
||||
|
||||
getSpotifyLibrary = (forceRefetch = false) => {
|
||||
const {
|
||||
source,
|
||||
spotify_available,
|
||||
coreActions: {
|
||||
loadLibrary,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (!spotify_available) return;
|
||||
if (source !== 'spotify' && source !== 'all') return;
|
||||
|
||||
loadLibrary('spotify:library:tracks', { forceRefetch });
|
||||
};
|
||||
|
||||
handleContextMenu = (e, item) => {
|
||||
const {
|
||||
uiActions: {
|
||||
showContextMenu,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
showContextMenu({
|
||||
e,
|
||||
context: 'album',
|
||||
uris: [item.uri],
|
||||
items: [item],
|
||||
});
|
||||
}
|
||||
|
||||
loadMore = () => {
|
||||
const {
|
||||
limit,
|
||||
per_page,
|
||||
} = this.state;
|
||||
const {
|
||||
location: {
|
||||
state,
|
||||
},
|
||||
history,
|
||||
} = this.props;
|
||||
|
||||
const new_limit = limit + per_page;
|
||||
this.setState({ limit: new_limit });
|
||||
history.replace({ state: { ...state, limit: new_limit } });
|
||||
}
|
||||
|
||||
setSort = (value) => {
|
||||
const {
|
||||
sort,
|
||||
sort_reverse,
|
||||
uiActions: {
|
||||
set,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
let reverse = false;
|
||||
if (sort === value) reverse = !sort_reverse;
|
||||
|
||||
set({
|
||||
library_tracks_sort_reverse: reverse,
|
||||
library_tracks_sort: value,
|
||||
});
|
||||
}
|
||||
|
||||
renderView = () => {
|
||||
const {
|
||||
sort,
|
||||
sort_reverse,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const {
|
||||
limit,
|
||||
filter,
|
||||
} = this.state;
|
||||
let { tracks } = this.props;
|
||||
|
||||
if (loading_progress < 1) {
|
||||
return <Loader body loading progress={loading_progress} />;
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
tracks = sortItems(tracks, sort, sort_reverse);
|
||||
}
|
||||
|
||||
if (filter && filter !== '') {
|
||||
tracks = applyFilter('name', filter, tracks);
|
||||
}
|
||||
|
||||
// Apply our lazy-load-rendering
|
||||
const total_tracks = tracks.length;
|
||||
tracks = tracks.slice(0, limit);
|
||||
|
||||
return (
|
||||
<section className="content-wrapper">
|
||||
<TrackList tracks={tracks} />
|
||||
<LazyLoadListener
|
||||
loadKey={total_tracks > limit ? limit : total_tracks}
|
||||
showLoader={limit < total_tracks}
|
||||
loadMore={this.loadMore}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
playAll() {
|
||||
this.props.spotifyActions.getLibraryTracksAndPlay();
|
||||
}
|
||||
render = () => {
|
||||
const {
|
||||
spotify_available,
|
||||
sort,
|
||||
source,
|
||||
sort_reverse,
|
||||
uiActions,
|
||||
loading_progress,
|
||||
} = this.props;
|
||||
const {
|
||||
filter,
|
||||
per_page,
|
||||
} = this.state;
|
||||
const loading = loading_progress < 1;
|
||||
|
||||
render() {
|
||||
// Note trailing "?" makes sure our context menu in_library checks doesn't interfere
|
||||
if (isLoading(this.props.load_queue, ['spotify_me/tracks?'])) {
|
||||
return (
|
||||
<div className="view library-tracks-view">
|
||||
<Header icon="music" title={i18n('library.tracks.title')} />
|
||||
<Loader body loading />
|
||||
</div>
|
||||
);
|
||||
const source_options = [
|
||||
{
|
||||
value: 'all',
|
||||
label: i18n('fields.filters.all'),
|
||||
},
|
||||
{
|
||||
value: 'local',
|
||||
label: i18n('services.mopidy.local'),
|
||||
},
|
||||
];
|
||||
|
||||
if (spotify_available) {
|
||||
source_options.push({
|
||||
value: 'spotify',
|
||||
label: i18n('services.spotify.title'),
|
||||
});
|
||||
}
|
||||
|
||||
const tracks = [];
|
||||
if (this.props.library_tracks && this.props.tracks) {
|
||||
for (let i = 0; i < this.props.library_tracks.length; i++) {
|
||||
const uri = this.props.library_tracks[i];
|
||||
if (this.props.tracks.hasOwnProperty(uri)) {
|
||||
tracks.push(this.props.tracks[uri]);
|
||||
}
|
||||
}
|
||||
}
|
||||
const sort_options = [
|
||||
{
|
||||
value: null,
|
||||
label: i18n('fields.filters.as_loaded'),
|
||||
},
|
||||
{
|
||||
value: 'name',
|
||||
label: i18n('fields.filters.name'),
|
||||
},
|
||||
{
|
||||
value: 'artists.first.name',
|
||||
label: i18n('fields.filters.artist'),
|
||||
},
|
||||
{
|
||||
value: 'last_modified',
|
||||
label: i18n('fields.filters.updated'),
|
||||
},
|
||||
{
|
||||
value: 'tracks_uris.length',
|
||||
label: i18n('fields.filters.tracks'),
|
||||
},
|
||||
{
|
||||
value: 'uri',
|
||||
label: i18n('fields.filters.source'),
|
||||
},
|
||||
];
|
||||
|
||||
const options = (
|
||||
<div className="header__options__wrapper">
|
||||
<FilterField
|
||||
initialValue={filter}
|
||||
handleChange={(value) => this.setState({ filter: value, limit: per_page })}
|
||||
onSubmit={() => uiActions.hideContextMenu()}
|
||||
/>
|
||||
<DropdownField
|
||||
icon="swap_vert"
|
||||
name={i18n('fields.sort')}
|
||||
value={sort}
|
||||
valueAsLabel
|
||||
options={sort_options}
|
||||
selected_icon={sort ? (sort_reverse ? 'keyboard_arrow_up' : 'keyboard_arrow_down') : null}
|
||||
handleChange={(val) => { this.setSort(val); uiActions.hideContextMenu(); }}
|
||||
/>
|
||||
<DropdownField
|
||||
icon="cloud"
|
||||
name={i18n('fields.source')}
|
||||
value={source}
|
||||
valueAsLabel
|
||||
options={source_options}
|
||||
handleChange={(val) => { uiActions.set({ library_tracks_source: val }); uiActions.hideContextMenu(); }}
|
||||
/>
|
||||
<Button
|
||||
onClick={(e) => this.playAll(e)}
|
||||
tracking={{ category: 'LibraryTracks', action: 'Play' }}
|
||||
noHover
|
||||
discrete
|
||||
onClick={loading ? this.cancelRefresh : this.refresh}
|
||||
tracking={{ category: 'LibraryTracks', action: 'Refresh' }}
|
||||
>
|
||||
<Icon name="play_circle_filled" />
|
||||
<I18n path="actions.play_all" />
|
||||
{loading ? <Icon name="close" /> : <Icon name="refresh" /> }
|
||||
{loading ? <I18n path="actions.cancel" /> : <I18n path="actions.refresh" /> }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="view library-tracks-view">
|
||||
<Header options={options} uiActions={this.props.uiActions}>
|
||||
<Icon name="music_note" type="material" />
|
||||
<I18n path="library.tracks.title" />
|
||||
<Header options={options} uiActions={uiActions}>
|
||||
<Icon name="album" type="material" />
|
||||
<I18n path="library.tracks.title" />
|
||||
</Header>
|
||||
<section className="content-wrapper">
|
||||
<TrackList tracks={tracks} />
|
||||
<LazyLoadListener
|
||||
loadKey={this.props.library_tracks_more}
|
||||
showLoader={this.props.library_tracks_more}
|
||||
loadMore={() => this.loadMore()}
|
||||
/>
|
||||
</section>
|
||||
{this.renderView()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const source = state.ui.library_tracks_source ? state.ui.library_tracks_source : 'all';
|
||||
|
||||
/**
|
||||
* Export our component
|
||||
*
|
||||
* We also integrate our global store, using connect()
|
||||
* */
|
||||
const libraryUris = [];
|
||||
if (source === 'all' || source === 'local') libraryUris.push('mopidy:library:tracks');
|
||||
if (source === 'all' || source === 'spotify') libraryUris.push('spotify:library:tracks');
|
||||
const librarySelector = makeLibrarySelector(libraryUris);
|
||||
const processProgressSelector = makeProcessProgressSelector(processKeys);
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
load_queue: state.ui.load_queue,
|
||||
tracks: state.core.tracks,
|
||||
spotify_available: state.spotify.access_token,
|
||||
library_tracks: state.spotify.library_tracks,
|
||||
library_tracks_more: state.spotify.library_tracks_more,
|
||||
});
|
||||
return {
|
||||
loading_progress: processProgressSelector(state),
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
tracks: librarySelector(state),
|
||||
spotify_available: state.spotify.access_token,
|
||||
view: state.ui.library_tracks_view,
|
||||
source,
|
||||
sort: state.ui.library_tracks_sort,
|
||||
sort_reverse: state.ui.library_tracks_sort_reverse,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
coreActions: bindActionCreators(coreActions, dispatch),
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
|
||||
Reference in New Issue
Block a user