Loading playlist library with new URI; Starting #600
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -106,7 +106,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1598691847";
|
||||
var build = "1599105011";
|
||||
var version = "3.52.4";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -610,6 +610,39 @@ class ContextMenu extends React.Component {
|
||||
hideContextMenu();
|
||||
}
|
||||
|
||||
reload = () => {
|
||||
const {
|
||||
uiActions: {
|
||||
hideContextMenu,
|
||||
},
|
||||
coreActions: {
|
||||
loadArtist,
|
||||
loadAlbum,
|
||||
loadPlaylist,
|
||||
},
|
||||
menu: {
|
||||
uris,
|
||||
} = {},
|
||||
} = this.props;
|
||||
|
||||
const uri = uris[0];
|
||||
|
||||
switch (uriType(uri)) {
|
||||
case 'artist':
|
||||
loadArtist(uri, true);
|
||||
break;
|
||||
case 'album':
|
||||
loadAlbum(uri, true);
|
||||
break;
|
||||
case 'playlist':
|
||||
loadPlaylist(uri, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hideContextMenu();
|
||||
}
|
||||
|
||||
renderTitle = () => {
|
||||
const {
|
||||
uiActions: {
|
||||
@ -1092,6 +1125,16 @@ class ContextMenu extends React.Component {
|
||||
</div>
|
||||
);
|
||||
|
||||
const reload = (
|
||||
<div className="context-menu__item">
|
||||
<a className="context-menu__item__link" onClick={this.reload}>
|
||||
<span className="context-menu__item__label">
|
||||
<I18n path="context_menu.reload" />
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
switch (context.name) {
|
||||
case 'album':
|
||||
return (
|
||||
@ -1104,6 +1147,7 @@ class ContextMenu extends React.Component {
|
||||
<div className="context-menu__divider" />
|
||||
{go_to_artist}
|
||||
{copy_uris}
|
||||
{reload}
|
||||
</div>
|
||||
);
|
||||
case 'artist':
|
||||
@ -1116,6 +1160,7 @@ class ContextMenu extends React.Component {
|
||||
<div className="context-menu__divider" />
|
||||
{context.source === 'spotify' && go_to_recommendations}
|
||||
{copy_uris}
|
||||
{reload}
|
||||
</div>
|
||||
);
|
||||
case 'playlist':
|
||||
@ -1138,6 +1183,7 @@ class ContextMenu extends React.Component {
|
||||
{delete_playlist}
|
||||
</div>
|
||||
)}
|
||||
{reload}
|
||||
</div>
|
||||
);
|
||||
case 'current-track':
|
||||
|
||||
@ -173,6 +173,7 @@ context_menu:
|
||||
discover_similar: Discover similar
|
||||
start_radio: Start radio
|
||||
copy_uri: Copy URI(s)
|
||||
reload: Reload
|
||||
dropzones:
|
||||
dragging_things: 'Dragging %{count} things'
|
||||
playback_controls:
|
||||
|
||||
@ -160,6 +160,14 @@ export function loadUserPlaylists(uri, force_reload = false) {
|
||||
};
|
||||
}
|
||||
|
||||
export function loadLibrary(uri, force_reload = false) {
|
||||
return {
|
||||
type: 'LOAD_LIBRARY',
|
||||
uri,
|
||||
force_reload,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Record loaders
|
||||
|
||||
@ -4,7 +4,7 @@ import ReactGA from 'react-ga';
|
||||
import localForage from 'localforage';
|
||||
import { arrayOf } from '../../util/arrays';
|
||||
import URILink from '../../components/URILink';
|
||||
import { uriSource, upgradeSpotifyPlaylistUris, uriType } from '../../util/helpers';
|
||||
import { uriSource, upgradeSpotifyPlaylistUris, uriType, titleCase } from '../../util/helpers';
|
||||
import {
|
||||
formatTracks,
|
||||
formatTrack,
|
||||
@ -348,20 +348,14 @@ const CoreMiddleware = (function () {
|
||||
break;
|
||||
|
||||
case 'LOAD_ALBUM':
|
||||
|
||||
// Load from Redux store
|
||||
if (
|
||||
!action.force_reload
|
||||
&& store.getState().core.albums[action.uri]
|
||||
&& store.getState().core.albums[action.uri].tracks_uris) {
|
||||
if (!action.force_reload && store.getState().core.items[action.uri]) {
|
||||
console.info(`Loading "${action.uri}" from index`);
|
||||
break;
|
||||
}
|
||||
|
||||
// Try our cold storage
|
||||
localForage.getItem(action.uri).then((result) => {
|
||||
|
||||
if (result) {
|
||||
if (result && !action.force_reload) {
|
||||
console.info(`Loading "${action.uri}" from database`);
|
||||
store.dispatch(coreActions.restoreFromColdStore(result));
|
||||
} else {
|
||||
@ -416,7 +410,7 @@ const CoreMiddleware = (function () {
|
||||
|
||||
// Try our cold storage
|
||||
localForage.getItem(action.uri).then((result) => {
|
||||
if (result) {
|
||||
if (result && !action.force_reload) {
|
||||
console.info(`Loading "${action.uri}" from database`);
|
||||
store.dispatch(coreActions.restoreFromColdStore(result));
|
||||
} else {
|
||||
@ -440,28 +434,39 @@ const CoreMiddleware = (function () {
|
||||
break;
|
||||
|
||||
case 'LOAD_PLAYLIST':
|
||||
if (
|
||||
!action.force_reload
|
||||
&& store.getState().core.playlists[action.uri]
|
||||
&& store.getState().core.playlists[action.uri].tracks_uris !== undefined
|
||||
) {
|
||||
console.info(`Loading "${action.uri}" from index`);
|
||||
const fetchPlaylist = () => {
|
||||
switch (uriSource(action.uri)) {
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getPlaylist(action.uri));
|
||||
|
||||
if (spotify.me) {
|
||||
store.dispatch(spotifyActions.following(action.uri));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
store.dispatch(mopidyActions.getPlaylist(action.uri));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (action.force_reload) {
|
||||
fetchPlaylist();
|
||||
break;
|
||||
}
|
||||
if (store.getState().core.items[action.uri]) {
|
||||
console.info(`Using "${action.uri}" from index`);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (uriSource(action.uri)) {
|
||||
case 'spotify':
|
||||
store.dispatch(spotifyActions.getPlaylist(action.uri));
|
||||
|
||||
if (spotify.me) {
|
||||
store.dispatch(spotifyActions.following(action.uri));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
store.dispatch(mopidyActions.getPlaylist(action.uri));
|
||||
break;
|
||||
}
|
||||
localForage.getItem(action.uri).then((result) => {
|
||||
if (result) {
|
||||
console.info(`Restoring "${action.uri}" from database`);
|
||||
store.dispatch(coreActions.restoreFromColdStore(result));
|
||||
} else {
|
||||
fetchPlaylist();
|
||||
}
|
||||
});
|
||||
|
||||
next(action);
|
||||
break;
|
||||
@ -514,6 +519,44 @@ const CoreMiddleware = (function () {
|
||||
next(action);
|
||||
break;
|
||||
|
||||
case 'LOAD_LIBRARY':
|
||||
const fetchLibrary = () => {
|
||||
switch (uriSource(action.uri)) {
|
||||
case 'spotify':
|
||||
store.dispatch(
|
||||
spotifyActions[`getLibrary${titleCase(uriType(action.uri))}`](action.uri),
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
store.dispatch(
|
||||
mopidyActions[`getLibrary${titleCase(uriType(action.uri))}`](action.uri),
|
||||
);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (action.force_reload) {
|
||||
fetchLibrary();
|
||||
break;
|
||||
}
|
||||
if (store.getState().core.items[action.uri]) {
|
||||
console.info(`Using "${action.uri}" from index`);
|
||||
break;
|
||||
}
|
||||
|
||||
localForage.getItem(action.uri).then((result) => {
|
||||
if (result) {
|
||||
console.info(`Restoring "${action.uri}" from database`);
|
||||
store.dispatch(coreActions.restoreFromColdStore(result));
|
||||
} else {
|
||||
fetchLibrary();
|
||||
}
|
||||
});
|
||||
|
||||
next(action);
|
||||
break;
|
||||
|
||||
|
||||
/**
|
||||
* Index actions
|
||||
|
||||
@ -1600,39 +1600,35 @@ const MopidyMiddleware = (function () {
|
||||
case 'MOPIDY_GET_LIBRARY_PLAYLISTS':
|
||||
request(store, 'playlists.asList')
|
||||
.then((response) => {
|
||||
// drop in our URI list
|
||||
const playlist_uris = arrayOf('uri', response);
|
||||
const playlist_uris_filtered = [];
|
||||
|
||||
// Remove any Spotify playlists. These will be handled by our Spotify API
|
||||
for (var i = 0; i < playlist_uris.length; i++) {
|
||||
if (uriSource(playlist_uris[i]) != 'spotify') {
|
||||
playlist_uris_filtered.push(playlist_uris[i]);
|
||||
}
|
||||
}
|
||||
|
||||
store.dispatch({ type: 'MOPIDY_LIBRARY_PLAYLISTS_LOADED', uris: playlist_uris_filtered });
|
||||
store.dispatch({ type: 'MOPIDY_LIBRARY_PLAYLISTS_LOADED_ALL' });
|
||||
const playlist_uris = arrayOf('uri', response).filter(
|
||||
(uri) => uriSource(uri) !== 'spotify',
|
||||
);
|
||||
const libraryPlaylists = [];
|
||||
|
||||
// get the full playlist objects
|
||||
for (var i = 0; i < playlist_uris_filtered.length; i++) {
|
||||
request(store, 'playlists.lookup', { uri: playlist_uris_filtered[i] })
|
||||
playlist_uris.forEach((uri, index) => {
|
||||
request(store, 'playlists.lookup', { uri })
|
||||
.then((response) => {
|
||||
const source = uriSource(response.uri);
|
||||
const playlist = {
|
||||
|
||||
libraryPlaylists.push({
|
||||
type: 'playlist',
|
||||
name: response.name,
|
||||
uri: response.uri,
|
||||
source,
|
||||
source: uriSource(response.uri),
|
||||
provider: 'mopidy',
|
||||
last_modified: response.last_modified,
|
||||
tracks_total: (response.tracks ? response.tracks.length : 0),
|
||||
};
|
||||
tracks: response.tracks,
|
||||
});
|
||||
|
||||
store.dispatch(coreActions.playlistLoaded(playlist));
|
||||
if (index === playlist_uris.length - 1) {
|
||||
store.dispatch(coreActions.itemLoaded({
|
||||
uri: 'mopidy:library:playlists',
|
||||
items: libraryPlaylists,
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
formatArtist,
|
||||
formatArtists,
|
||||
formatAlbums,
|
||||
formatPlaylists,
|
||||
} from '../../util/format';
|
||||
import URILink from '../../components/URILink';
|
||||
import { i18n } from '../../locale';
|
||||
@ -1403,6 +1404,8 @@ export function getPlaylist(uri) {
|
||||
request(dispatch, getState, `playlists/${getFromUri('playlistid', uri)}?market=${getState().spotify.country}`)
|
||||
.then(
|
||||
(response) => {
|
||||
let tracks = formatTracks(response.tracks.items);
|
||||
|
||||
// convert links in description
|
||||
let description = null;
|
||||
if (response.description) {
|
||||
@ -1412,22 +1415,29 @@ export function getPlaylist(uri) {
|
||||
description = description.split('<a href="spotify:user:').join('<a href="#' + '/user/spotify:user:');
|
||||
}
|
||||
|
||||
const tracks = formatTracks(response.tracks.items);
|
||||
|
||||
const playlist = {
|
||||
|
||||
dispatch(coreActions.itemLoaded({
|
||||
...formatPlaylist(response),
|
||||
is_completely_loaded: true,
|
||||
user_uri: response.owner.uri,
|
||||
tracks_uris: tracks ? arrayOf('uri', tracks) : null,
|
||||
tracks_more: response.tracks.next,
|
||||
tracks_total: response.tracks.total,
|
||||
user: formatUser(response.owner),
|
||||
tracks,
|
||||
description,
|
||||
};
|
||||
}));
|
||||
|
||||
dispatch(coreActions.userLoaded(formatUser(response.owner)));
|
||||
dispatch(coreActions.tracksLoaded(tracks));
|
||||
dispatch(coreActions.playlistLoaded(playlist));
|
||||
const fetchTracks = (endpoint) => request(dispatch, getState, endpoint)
|
||||
.then((response) => {
|
||||
tracks = [...tracks, ...formatTracks(response.items)];
|
||||
if (response.next) {
|
||||
fetchTracks(response.next);
|
||||
} else {
|
||||
dispatch(coreActions.itemLoaded({
|
||||
uri,
|
||||
tracks,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
if (response.tracks.next) {
|
||||
fetchTracks(response.tracks.next);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
dispatch(coreActions.handleException(
|
||||
@ -1721,6 +1731,23 @@ export function flushLibrary() {
|
||||
|
||||
export function getLibraryPlaylists() {
|
||||
return (dispatch, getState) => {
|
||||
let libraryPlaylists = [];
|
||||
const fetchLibraryPlaylists = (endpoint) => request(dispatch, getState, endpoint)
|
||||
.then((response) => {
|
||||
libraryPlaylists = [...libraryPlaylists, ...formatPlaylists(response.items)];
|
||||
console.log('loaded page of playlists', response.items);
|
||||
if (response.next) {
|
||||
fetchLibraryPlaylists(response.next);
|
||||
} else {
|
||||
dispatch(coreActions.itemLoaded({
|
||||
uri: 'spotify:library:playlists',
|
||||
items: libraryPlaylists,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
fetchLibraryPlaylists('me/playlists?limit=50');
|
||||
/*
|
||||
const last_run = getState().ui.processes.SPOTIFY_GET_LIBRARY_PLAYLISTS_PROCESSOR;
|
||||
|
||||
if (!last_run) {
|
||||
@ -1732,6 +1759,7 @@ export function getLibraryPlaylists() {
|
||||
} else if (last_run.status === 'finished' && !getState().spotify.library_playlists_loaded_all) {
|
||||
dispatch(uiActions.startProcess('SPOTIFY_GET_LIBRARY_PLAYLISTS_PROCESSOR', 'Loading Spotify playlists', { next: 'me/playlists?limit=50' }));
|
||||
}
|
||||
*/
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -247,7 +247,7 @@ const formatArtists = function (records = []) {
|
||||
const formatPlaylists = function (records = []) {
|
||||
const formatted = [];
|
||||
for (const record of records) {
|
||||
formatted.push(formatTrack(record));
|
||||
formatted.push(formatPlaylist(record));
|
||||
}
|
||||
return formatted;
|
||||
};
|
||||
@ -411,10 +411,7 @@ const formatPlaylist = function (data) {
|
||||
'last_modified',
|
||||
'can_edit',
|
||||
'owner',
|
||||
'user_uri',
|
||||
'tracks_uris',
|
||||
'tracks_total',
|
||||
'tracks_more',
|
||||
'tracks',
|
||||
];
|
||||
|
||||
// Loop fields and import from data
|
||||
|
||||
@ -176,6 +176,8 @@ const uriType = function (uri) {
|
||||
}
|
||||
|
||||
switch (exploded[1]) {
|
||||
case 'library':
|
||||
return exploded[2];
|
||||
case 'track':
|
||||
case 'artist':
|
||||
case 'album':
|
||||
|
||||
@ -83,27 +83,6 @@ class Playlist extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
loadMore = () => {
|
||||
const {
|
||||
spotifyActions: {
|
||||
getMore,
|
||||
},
|
||||
playlist: {
|
||||
uri,
|
||||
tracks_more,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
getMore(
|
||||
tracks_more,
|
||||
{
|
||||
parent_type: 'playlist',
|
||||
parent_key: uri,
|
||||
records_type: 'track',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
handleContextMenu = (e) => {
|
||||
const {
|
||||
uiActions: {
|
||||
@ -163,7 +142,16 @@ class Playlist extends React.Component {
|
||||
}
|
||||
|
||||
removeTracks = (tracks_indexes) => {
|
||||
this.props.coreActions.removeTracksFromPlaylist(this.props.playlist.uri, tracks_indexes);
|
||||
const {
|
||||
coreActions: {
|
||||
removeTracksFromPlaylist,
|
||||
},
|
||||
playlist: {
|
||||
uri,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
removeTracksFromPlaylist(uri, tracks_indexes);
|
||||
}
|
||||
|
||||
inLibrary = () => {
|
||||
@ -283,16 +271,14 @@ class Playlist extends React.Component {
|
||||
render = () => {
|
||||
const {
|
||||
uri,
|
||||
playlist: playlistProp,
|
||||
playlist,
|
||||
load_queue,
|
||||
tracks,
|
||||
users,
|
||||
slim_mode,
|
||||
} = this.props;
|
||||
|
||||
const playlist_id = getFromUri('playlistid', uri);
|
||||
|
||||
if (!playlistProp) {
|
||||
if (!playlist) {
|
||||
if (isLoading(load_queue, [`spotify_playlists/${playlist_id}?`])) {
|
||||
return <Loader body loading />
|
||||
}
|
||||
@ -305,22 +291,11 @@ class Playlist extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
const playlist = collate(playlistProp, { tracks, users });
|
||||
|
||||
let context = 'playlist';
|
||||
if (playlist.can_edit) {
|
||||
context = 'editable-playlist';
|
||||
}
|
||||
|
||||
const is_loading_tracks = (
|
||||
playlist.tracks_total !== 0
|
||||
&& (
|
||||
!playlist.tracks_uris
|
||||
|| (playlist.tracks_uris && !playlist.tracks)
|
||||
|| (playlist.tracks_uris.length !== playlist.tracks.length)
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="view playlist-view content-wrapper preserve-3d">
|
||||
|
||||
@ -383,11 +358,6 @@ class Playlist extends React.Component {
|
||||
removeTracks={this.removeTracks}
|
||||
reorderTracks={this.reorderTracks}
|
||||
/>
|
||||
<LazyLoadListener
|
||||
loadKey={playlist.tracks_more}
|
||||
showLoader={is_loading_tracks || playlist.tracks_more}
|
||||
loadMore={this.loadMore}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
@ -403,9 +373,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
load_queue,
|
||||
} = {},
|
||||
core: {
|
||||
users,
|
||||
tracks,
|
||||
playlists,
|
||||
items,
|
||||
} = {},
|
||||
spotify: {
|
||||
library_playlists: spotify_library_playlists,
|
||||
@ -425,9 +393,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
slim_mode,
|
||||
theme,
|
||||
load_queue,
|
||||
users,
|
||||
tracks,
|
||||
playlist: (playlists[uri] !== undefined ? playlists[uri] : false),
|
||||
playlist: items[uri] || null,
|
||||
spotify_library_playlists,
|
||||
local_library_playlists,
|
||||
spotify_authorized,
|
||||
|
||||
@ -46,34 +46,29 @@ class LibraryPlaylists extends React.Component {
|
||||
getMopidyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
mopidy_library_playlists,
|
||||
mopidyActions: {
|
||||
getLibraryPlaylists,
|
||||
coreActions: {
|
||||
loadLibrary,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (source !== 'local' && source !== 'all') return;
|
||||
if (mopidy_library_playlists) return;
|
||||
|
||||
getLibraryPlaylists();
|
||||
loadLibrary('mopidy:library:playlists');
|
||||
};
|
||||
|
||||
getSpotifyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
spotify_available,
|
||||
spotify_library_playlists_status,
|
||||
spotifyActions: {
|
||||
getLibraryPlaylists,
|
||||
coreActions: {
|
||||
loadLibrary,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (!spotify_available) return;
|
||||
if (source !== 'spotify' && source !== 'all') return;
|
||||
if (spotify_library_playlists_status === 'finished') return;
|
||||
if (spotify_library_playlists_status === 'started') return;
|
||||
|
||||
getLibraryPlaylists();
|
||||
loadLibrary('spotify:library:playlists');
|
||||
};
|
||||
|
||||
componentDidUpdate = ({ source: prevSource }) => {
|
||||
@ -117,28 +112,20 @@ class LibraryPlaylists extends React.Component {
|
||||
this.props.uiActions.set(data);
|
||||
}
|
||||
|
||||
renderView() {
|
||||
let playlists = [];
|
||||
renderView = () => {
|
||||
const {
|
||||
spotify_library_playlists: {
|
||||
items: spotify_playlists,
|
||||
},
|
||||
mopidy_library_playlists: {
|
||||
items: mopidy_playlists,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
// Spotify library items
|
||||
if (this.props.spotify_library_playlists && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
for (var i = 0; i < this.props.spotify_library_playlists.length; i++) {
|
||||
var uri = this.props.spotify_library_playlists[i];
|
||||
if (this.props.playlists.hasOwnProperty(uri)) {
|
||||
playlists.push(this.props.playlists[uri]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mopidy library items
|
||||
if (this.props.mopidy_library_playlists && (this.props.source == 'all' || this.props.source == 'local')) {
|
||||
for (var i = 0; i < this.props.mopidy_library_playlists.length; i++) {
|
||||
var uri = this.props.mopidy_library_playlists[i];
|
||||
if (this.props.playlists.hasOwnProperty(uri)) {
|
||||
playlists.push(this.props.playlists[uri]);
|
||||
}
|
||||
}
|
||||
}
|
||||
let playlists = [
|
||||
...spotify_playlists,
|
||||
...mopidy_playlists,
|
||||
];
|
||||
|
||||
if (this.props.sort) {
|
||||
playlists = sortItems(playlists, this.props.sort, this.props.sort_reverse);
|
||||
@ -308,11 +295,9 @@ class LibraryPlaylists extends React.Component {
|
||||
const mapStateToProps = (state) => ({
|
||||
slim_mode: state.ui.slim_mode,
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
mopidy_library_playlists: state.mopidy.library_playlists,
|
||||
mopidy_library_playlists_status: (state.ui.processes.MOPIDY_LIBRARY_PLAYLISTS_PROCESSOR !== undefined ? state.ui.processes.MOPIDY_LIBRARY_PLAYLISTS_PROCESSOR.status : null),
|
||||
spotify_available: state.spotify.access_token,
|
||||
spotify_library_playlists: state.spotify.library_playlists,
|
||||
spotify_library_playlists_status: (state.ui.processes.SPOTIFY_GET_LIBRARY_PLAYLISTS_PROCESSOR !== undefined ? state.ui.processes.SPOTIFY_GET_LIBRARY_PLAYLISTS_PROCESSOR.status : null),
|
||||
mopidy_library_playlists: state.core.items['mopidy:library:playlists'] || { items: [] },
|
||||
spotify_library_playlists: state.core.items['spotify:library:playlists'] || { items: [] },
|
||||
load_queue: state.ui.load_queue,
|
||||
me_id: (state.spotify.me ? state.spotify.me.id : false),
|
||||
view: state.ui.library_playlists_view,
|
||||
|
||||
Reference in New Issue
Block a user