Sensibly detecting Spotify availability by access_token; Only fetch playlists to add tracks to from relevant providers, fixes #539
This commit is contained in:
@ -25,6 +25,7 @@ import {
|
||||
getFromUri,
|
||||
isLoading,
|
||||
sourceIcon,
|
||||
decodeMopidyUri,
|
||||
} from '../util/helpers';
|
||||
import { collate } from '../util/format';
|
||||
|
||||
@ -290,9 +291,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
spotify: {
|
||||
library_playlists: spotify_library_playlists,
|
||||
authorization: spotify_authorized,
|
||||
me: {
|
||||
id: spotify_userid,
|
||||
} = {},
|
||||
me = {},
|
||||
} = {},
|
||||
mopidy: {
|
||||
connected: mopidy_connected,
|
||||
@ -300,16 +299,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
} = {},
|
||||
} = state;
|
||||
|
||||
// Decode the URI, and then re-encode selected characters
|
||||
// This is needed as Mopidy encodes *some* characters in playlist URIs (but not other characters)
|
||||
// We need to retain ":" because this a reserved URI separator
|
||||
let uri = decodeURIComponent(ownProps.match.params.uri);
|
||||
uri = uri.replace(/\s/g, '%20'); // space
|
||||
uri = uri.replace(/\[/g, '%5B'); // [
|
||||
uri = uri.replace(/\]/g, '%5D'); // ]
|
||||
uri = uri.replace(/\(/g, '%28'); // (
|
||||
uri = uri.replace(/\)/g, '%29'); // )
|
||||
uri = uri.replace(/\#/g, '%23'); // #
|
||||
const uri = decodeMopidyUri(ownProps.match.params.uri);
|
||||
|
||||
return {
|
||||
uri,
|
||||
@ -324,7 +314,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
local_library_playlists,
|
||||
mopidy_connected,
|
||||
spotify_authorized,
|
||||
spotify_userid,
|
||||
spotify_userid: (me && me.id) || null,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -46,11 +46,11 @@ class LibraryAlbums extends React.Component {
|
||||
this.props.mopidyActions.getLibraryAlbums();
|
||||
}
|
||||
|
||||
if (this.props.google_enabled && this.props.google_library_albums_status != 'finished' && this.props.google_library_albums_status != 'started' && (this.props.source == 'all' || this.props.source == 'google')) {
|
||||
if (this.props.google_available && this.props.google_library_albums_status != 'finished' && this.props.google_library_albums_status != 'started' && (this.props.source == 'all' || this.props.source == 'google')) {
|
||||
this.props.googleActions.getLibraryAlbums();
|
||||
}
|
||||
|
||||
if (this.props.spotify_enabled && this.props.spotify_library_albums_status != 'finished' && this.props.spotify_library_albums_status != 'started' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
if (this.props.spotify_available && this.props.spotify_library_albums_status != 'finished' && this.props.spotify_library_albums_status != 'started' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
this.props.spotifyActions.getLibraryAlbums();
|
||||
}
|
||||
}
|
||||
@ -60,8 +60,8 @@ class LibraryAlbums extends React.Component {
|
||||
}) => {
|
||||
const {
|
||||
mopidy_connected,
|
||||
google_enabled,
|
||||
spotify_enabled,
|
||||
google_available,
|
||||
spotify_available,
|
||||
source,
|
||||
mopidyActions,
|
||||
googleActions,
|
||||
@ -80,14 +80,14 @@ class LibraryAlbums extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (google_enabled && (source == 'all' || source == 'google')) {
|
||||
if (google_available && (source == 'all' || source == 'google')) {
|
||||
// Filter changed, but we haven't got this provider's library yet
|
||||
if (source !== 'all' && source !== 'google' && google_library_albums_status !== 'finished' && google_library_albums_status !== 'started') {
|
||||
googleActions.getLibraryAlbums();
|
||||
}
|
||||
}
|
||||
|
||||
if (spotify_enabled && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_available && (source === 'all' || source === 'spotify')) {
|
||||
// Filter changed, but we haven't got this provider's library yet
|
||||
if (spotify_library_albums_status !== 'finished' && spotify_library_albums_status !== 'started') {
|
||||
spotifyActions.getLibraryAlbums();
|
||||
@ -256,14 +256,14 @@ class LibraryAlbums extends React.Component {
|
||||
},
|
||||
];
|
||||
|
||||
if (this.props.spotify_enabled) {
|
||||
if (this.props.spotify_available) {
|
||||
source_options.push({
|
||||
value: 'spotify',
|
||||
label: 'Spotify',
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.google_enabled) {
|
||||
if (this.props.google_available) {
|
||||
source_options.push({
|
||||
value: 'google',
|
||||
label: 'Google',
|
||||
@ -363,10 +363,10 @@ const mapStateToProps = (state, ownProps) => ({
|
||||
albums: state.core.albums,
|
||||
mopidy_library_albums: state.mopidy.library_albums,
|
||||
mopidy_library_albums_status: (state.ui.processes.MOPIDY_LIBRARY_ALBUMS_PROCESSOR !== undefined ? state.ui.processes.MOPIDY_LIBRARY_ALBUMS_PROCESSOR.status : null),
|
||||
google_enabled: state.google.enabled,
|
||||
google_available: (state.mopidy.uri_schemes && state.mopidy.uri_schemes.includes('gmusic:')),
|
||||
google_library_albums: state.google.library_albums,
|
||||
google_library_albums_status: (state.ui.processes.GOOGLE_LIBRARY_ALBUMS_PROCESSOR !== undefined ? state.ui.processes.GOOGLE_LIBRARY_ALBUMS_PROCESSOR.status : null),
|
||||
spotify_enabled: state.spotify.enabled,
|
||||
spotify_available: state.spotify.access_token,
|
||||
spotify_library_albums: state.spotify.library_albums,
|
||||
spotify_library_albums_status: (state.ui.processes.SPOTIFY_GET_LIBRARY_ALBUMS_PROCESSOR !== undefined ? state.ui.processes.SPOTIFY_GET_LIBRARY_ALBUMS_PROCESSOR.status : null),
|
||||
view: state.ui.library_albums_view,
|
||||
|
||||
@ -44,11 +44,11 @@ class LibraryArtists extends React.Component {
|
||||
this.props.mopidyActions.getLibraryArtists();
|
||||
}
|
||||
|
||||
if (this.props.google_enabled && !this.props.google_library_artists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'google')) {
|
||||
if (this.props.google_available && !this.props.google_library_artists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'google')) {
|
||||
this.props.googleActions.getLibraryArtists();
|
||||
}
|
||||
|
||||
if (this.props.spotify_enabled && this.props.spotify_library_artists_status != 'finished' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
if (this.props.spotify_available && this.props.spotify_library_artists_status != 'finished' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
this.props.spotifyActions.getLibraryArtists();
|
||||
}
|
||||
}
|
||||
@ -59,8 +59,8 @@ class LibraryArtists extends React.Component {
|
||||
const {
|
||||
source,
|
||||
mopidy_connected,
|
||||
google_enabled,
|
||||
spotify_enabled,
|
||||
google_available,
|
||||
spotify_available,
|
||||
mopidyActions,
|
||||
googleActions,
|
||||
spotifyActions,
|
||||
@ -68,7 +68,7 @@ class LibraryArtists extends React.Component {
|
||||
google_library_artists,
|
||||
spotify_library_artists_status,
|
||||
} = this.props;
|
||||
|
||||
|
||||
if (mopidy_connected && (source === 'all' || source === 'local')) {
|
||||
if (!prev_mopidy_connected) mopidyActions.getLibraryArtists();
|
||||
|
||||
@ -77,13 +77,13 @@ class LibraryArtists extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (mopidy_connected && google_enabled && (source === 'all' || source === 'google')) {
|
||||
if (mopidy_connected && google_available && (source === 'all' || source === 'google')) {
|
||||
if (source !== 'all' && source !== 'google' && !google_library_artists) {
|
||||
googleActions.getLibraryArtists();
|
||||
}
|
||||
}
|
||||
|
||||
if (spotify_enabled && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_available && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_library_artists_status !== 'finished' && spotify_library_artists_status !== 'started') {
|
||||
spotifyActions.getLibraryArtists();
|
||||
}
|
||||
@ -232,14 +232,14 @@ class LibraryArtists extends React.Component {
|
||||
},
|
||||
];
|
||||
|
||||
if (this.props.spotify_enabled) {
|
||||
if (this.props.spotify_available) {
|
||||
source_options.push({
|
||||
value: 'spotify',
|
||||
label: 'Spotify',
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.google_enabled) {
|
||||
if (this.props.google_available) {
|
||||
source_options.push({
|
||||
value: 'google',
|
||||
label: 'Google',
|
||||
@ -323,20 +323,13 @@ class LibraryArtists extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export our component
|
||||
*
|
||||
* We also integrate our global store, using connect()
|
||||
* */
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
mopidy_library_artists: state.mopidy.library_artists,
|
||||
google_enabled: state.google.enabled,
|
||||
google_available: (state.mopidy.uri_schemes && state.mopidy.uri_schemes.includes('gmusic:')),
|
||||
google_library_artists: state.google.library_artists,
|
||||
spotify_enabled: state.spotify.enabled,
|
||||
spotify_available: state.spotify.access_token,
|
||||
spotify_library_artists: state.spotify.library_artists,
|
||||
spotify_library_artists_status: (state.ui.processes.SPOTIFY_GET_LIBRARY_ARTISTS_PROCESSOR !== undefined ? state.ui.processes.SPOTIFY_GET_LIBRARY_ARTISTS_PROCESSOR.status : null),
|
||||
artists: state.core.artists,
|
||||
|
||||
@ -42,7 +42,7 @@ class LibraryPlaylists extends React.Component {
|
||||
this.props.mopidyActions.getLibraryPlaylists();
|
||||
}
|
||||
|
||||
if (this.props.spotify_enabled && this.props.spotify_library_playlists_status !== 'finished' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
if (this.props.spotify_available && this.props.spotify_library_playlists_status !== 'finished' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
this.props.spotifyActions.getLibraryPlaylists();
|
||||
}
|
||||
}
|
||||
@ -54,7 +54,7 @@ class LibraryPlaylists extends React.Component {
|
||||
source,
|
||||
mopidy_connected,
|
||||
mopidy_library_playlists,
|
||||
spotify_enabled,
|
||||
spotify_available,
|
||||
spotify_library_playlists_status,
|
||||
mopidyActions,
|
||||
spotifyActions,
|
||||
@ -68,7 +68,7 @@ class LibraryPlaylists extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (spotify_enabled && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_available && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_library_playlists_status !== 'finished' && spotify_library_playlists_status !== 'started') {
|
||||
spotifyActions.getLibraryPlaylists();
|
||||
}
|
||||
@ -190,7 +190,7 @@ class LibraryPlaylists extends React.Component {
|
||||
},
|
||||
];
|
||||
|
||||
if (this.props.spotify_enabled) {
|
||||
if (this.props.spotify_available) {
|
||||
source_options.push({
|
||||
value: 'spotify',
|
||||
label: 'Spotify',
|
||||
@ -296,7 +296,7 @@ const mapStateToProps = (state, ownProps) => ({
|
||||
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_enabled: (state.mopidy.uri_schemes && state.mopidy.uri_schemes.includes('spotify:')),
|
||||
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),
|
||||
load_queue: state.ui.load_queue,
|
||||
|
||||
@ -16,7 +16,7 @@ class LibraryTracks extends React.Component {
|
||||
componentDidMount() {
|
||||
this.props.uiActions.setWindowTitle('Tracks');
|
||||
|
||||
if (!this.props.spotify_me) {
|
||||
if (!this.props.spotify_available) {
|
||||
this.props.uiActions.createNotification({ level: 'warning', content: 'Enable Spotify to browse tracks' });
|
||||
} else if (this.props.library_tracks === undefined) {
|
||||
this.props.spotifyActions.getLibraryTracks();
|
||||
@ -94,7 +94,7 @@ Play all
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
load_queue: state.ui.load_queue,
|
||||
tracks: state.core.tracks,
|
||||
spotify_me: state.spotify.me,
|
||||
spotify_available: state.spotify.access_token,
|
||||
library_tracks: state.spotify.library_tracks,
|
||||
library_tracks_more: state.spotify.library_tracks_more,
|
||||
});
|
||||
|
||||
@ -10,7 +10,7 @@ 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 { sourceIcon } from '../../util/helpers';
|
||||
import { sourceIcon, decodeMopidyUri } from '../../util/helpers';
|
||||
import { sortItems } from '../../util/arrays';
|
||||
|
||||
class AddToPlaylist extends React.Component {
|
||||
@ -19,11 +19,12 @@ class AddToPlaylist extends React.Component {
|
||||
spotify_library_playlists_status,
|
||||
mopidy_library_playlists_status,
|
||||
mopidy_connected,
|
||||
spotify_available,
|
||||
spotifyActions,
|
||||
mopidyActions,
|
||||
} = this.props;
|
||||
|
||||
if (!spotify_library_playlists_status || spotify_library_playlists_status !== 'finished') {
|
||||
if ((!spotify_library_playlists_status || spotify_library_playlists_status !== 'finished') && spotify_available) {
|
||||
spotifyActions.getLibraryPlaylists();
|
||||
}
|
||||
|
||||
@ -32,13 +33,19 @@ class AddToPlaylist extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
playlistSelected(playlist_uri) {
|
||||
const { coreActions, uris } = this.props;
|
||||
coreActions.addTracksToPlaylist(playlist_uri, uris);
|
||||
playlistSelected = (playlist_uri) => {
|
||||
const {
|
||||
coreActions: {
|
||||
addTracksToPlaylist,
|
||||
},
|
||||
uris,
|
||||
} = this.props;
|
||||
const encodedUris = uris.map((uri) => decodeMopidyUri(uri));
|
||||
addTracksToPlaylist(playlist_uri, encodedUris);
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
render() {
|
||||
render = () =>{
|
||||
const { playlists, uris, spotify_library_playlists_status } = this.props;
|
||||
|
||||
if (!playlists) return <div className="empty">No editable playlists</div>;
|
||||
@ -71,13 +78,11 @@ class AddToPlaylist extends React.Component {
|
||||
<ul className="list__item__details details">
|
||||
<li><Icon type="fontawesome" className="source" name={sourceIcon(playlist.uri)} /></li>
|
||||
<li>
|
||||
{ playlist.tracks_total ? (
|
||||
{playlist.tracks_total && (
|
||||
<span className="mid_grey-text">
|
||||
{ playlist.tracks_total }
|
||||
{' '}
|
||||
tracks
|
||||
{`${playlist.tracks_total} tracks`}
|
||||
</span>
|
||||
) : null }
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -95,6 +100,7 @@ const mapStateToProps = (state, ownProps) => ({
|
||||
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),
|
||||
load_queue: state.ui.load_queue,
|
||||
|
||||
@ -12,7 +12,7 @@ class CreatePlaylist extends React.Component {
|
||||
this.state = {
|
||||
name: '',
|
||||
description: '',
|
||||
scheme: 'spotify',
|
||||
scheme: 'm3u',
|
||||
is_public: true,
|
||||
is_collaborative: false,
|
||||
};
|
||||
@ -116,7 +116,9 @@ class CreatePlaylist extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
render = () => {
|
||||
const { spotify_available } = this.props;
|
||||
|
||||
return (
|
||||
<Modal className="modal--create-playlist">
|
||||
<h1>Create playlist</h1>
|
||||
@ -131,21 +133,22 @@ class CreatePlaylist extends React.Component {
|
||||
<input
|
||||
type="radio"
|
||||
name="scheme"
|
||||
value="spotify"
|
||||
checked={this.state.scheme == 'spotify'}
|
||||
value="m3u"
|
||||
checked={this.state.scheme === 'm3u'}
|
||||
onChange={(e) => this.setState({ scheme: e.target.value })}
|
||||
/>
|
||||
<span className="label">Spotify</span>
|
||||
<span className="label">Mopidy</span>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="scheme"
|
||||
value="m3u"
|
||||
checked={this.state.scheme == 'm3u'}
|
||||
value="spotify"
|
||||
disabled={!spotify_available }
|
||||
checked={this.state.scheme === 'spotify'}
|
||||
onChange={(e) => this.setState({ scheme: e.target.value })}
|
||||
/>
|
||||
<span className="label">Mopidy</span>
|
||||
<span className="label">Spotify</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -162,7 +165,9 @@ class CreatePlaylist extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({});
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
spotify_available: state.spotify.access_token,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
coreActions: bindActionCreators(coreActions, dispatch),
|
||||
|
||||
Reference in New Issue
Block a user