Assets accept name in URL so we can load simple playlists (eg Tidal) that don't respond to playlists.lookup

This commit is contained in:
James Barnsley
2021-05-29 12:04:41 +12:00
parent d90d7c6123
commit 2fc20638fa
10 changed files with 156 additions and 90 deletions

View File

@ -344,16 +344,16 @@ export class App extends React.Component {
path="/search/:type?/:term?"
component={Search}
/>
<Route exact path="/album/:uri" component={Album} />
<Route
exact
path="/artist/:uri/:sub_view?"
component={Artist}
/>
<Route exact path="/playlist/:uri" component={Playlist} />
<Route exact path="/user/:uri" component={User} />
<Route exact path="/track/:uri" component={Track} />
<Route exact path="/uri/:uri" component={UriRedirect} />
<Route exact path="/album/:uri/:name?" component={Album} />
<Route exact path="/playlist/:uri/:name?" component={Playlist} />
<Route exact path="/user/:uri/:name?" component={User} />
<Route exact path="/track/:uri/:name?" component={Track} />
<Route exact path="/uri/:uri/:name?" component={UriRedirect} />
<Route
exact

View File

@ -109,7 +109,7 @@ const GridItem = ({
} else if (item.link) {
to = item.link;
} else {
to = `/${item.type}/${encodeUri(item.uri)}`;
to = `/${item.type}/${encodeUri(item.uri)}${item.name ? `/${item.name}` : ''}`;
}
return (

View File

@ -138,7 +138,7 @@ const ListItem = ({
} else if (item.link) {
to = item.link;
} else {
to = `/${item.type}/${encodeUri(item.uri)}`;
to = `/${item.type}/${encodeUri(item.uri)}${item.name ? `/${item.name}` : ''}`;
}
if (e.target.tagName.toLowerCase() !== 'a') {

View File

@ -1180,41 +1180,60 @@ const MopidyMiddleware = (function () {
break;
}
case 'MOPIDY_GET_PLAYLIST':
request(store, 'playlists.lookup', { uri: action.uri })
.then((response) => {
if (!response) return;
const playlist = formatPlaylist({
...response,
uri: action.uri, // Patch in the requested URI
type: 'playlist',
provider: 'mopidy',
can_edit: true,
});
if (response.tracks) {
request(store, 'library.lookup', { uris: arrayOf('uri', response.tracks) })
.then((tracksResponse) => {
const tracks = response.tracks.map((simpleTrack) => {
const fullTracks = tracksResponse[simpleTrack.uri];
return {
...simpleTrack,
...(fullTracks.length ? fullTracks[0] : {}),
};
});
playlist.tracks = injectSortId(formatTracks(tracks));
store.dispatch(coreActions.itemLoaded(playlist));
case 'MOPIDY_GET_PLAYLIST': {
const processResponse = (response, fetchTracks = true) => {
const playlist = formatPlaylist({
can_edit: true,
provider: 'mopidy',
...response,
uri: action.uri, // Patch in the requested URI
type: 'playlist',
});
if (response.tracks && fetchTracks) {
request(store, 'library.lookup', { uris: arrayOf('uri', response.tracks) })
.then((tracksResponse) => {
const tracks = response.tracks.map((simpleTrack) => {
const fullTracks = tracksResponse[simpleTrack.uri];
return {
...simpleTrack,
...(fullTracks.length ? fullTracks[0] : {}),
};
});
} else {
store.dispatch(coreActions.itemLoaded(playlist));
}
playlist.tracks = injectSortId(formatTracks(tracks));
store.dispatch(coreActions.itemLoaded(playlist));
});
} else {
store.dispatch(coreActions.itemLoaded(playlist));
}
if (!playlist.images) {
store.dispatch(mopidyActions.getImages([playlist.uri]));
if (!playlist.images) {
store.dispatch(mopidyActions.getImages([playlist.uri]));
}
};
request(store, 'playlists.lookup', { uri: action.uri })
.then((playlistResponse) => {
if (playlistResponse) {
// Got a playlist from our playlists core, this is typically because it's a local
// playlist, or one that our backend user owns.
processResponse(playlistResponse);
} else {
console.info('Playlist not in playlists, fetching using library', action.uri);
// No match, so let's try fetching from foreign provider. This needs to happen when we
// don't have a HTTP API (eg Spotify) but the playlist is not ours (eg Tidal browse)
request(store, 'library.lookup', { uris: [action.uri] })
.then(({ [action.uri]: libraryResponse } = {}) => {
if (!libraryResponse) return;
processResponse({
tracks: libraryResponse,
can_edit: false,
...action.options.name ? { name: action.options.name } : {},
}, false);
});
}
});
break;
}
case 'MOPIDY_ADD_PLAYLIST_TRACKS':
request(store, 'playlists.lookup', { uri: action.key })
@ -1728,6 +1747,7 @@ const MopidyMiddleware = (function () {
}
if (subdirectoryImagesToLoad.length) {
console.info(`Loading ${subdirectoryImagesToLoad.length} subdirectory URIs`);
request(store, 'library.getImages', { uris: subdirectoryImagesToLoad })
.then((response) => {
const subdirectoriesWithImages = subdirectories.map((subdir) => {

View File

@ -53,9 +53,10 @@ class Playlist extends React.Component {
loadPlaylist,
},
uri,
name,
} = this.props;
this.setWindowTitle();
setTimeout(() => loadPlaylist(uri, { full: true }), 1);
setTimeout(() => loadPlaylist(uri, { full: true, name }), 1);
}
componentDidUpdate = ({
@ -64,6 +65,7 @@ class Playlist extends React.Component {
}) => {
const {
uri,
name,
playlist,
coreActions: {
loadPlaylist,
@ -78,7 +80,7 @@ class Playlist extends React.Component {
}
if (uri !== prevUri) {
loadPlaylist(uri, { full: true });
loadPlaylist(uri, { full: true, name });
}
if (!prevPlaylist && playlist) this.setWindowTitle(playlist);
@ -99,12 +101,13 @@ class Playlist extends React.Component {
},
playlist,
uri,
name,
} = this.props;
showContextMenu({
e,
context: 'playlist',
items: [playlist],
items: [{ name, ...playlist }],
uris: [uri],
});
}
@ -502,6 +505,7 @@ const mapStateToProps = (state, ownProps) => {
return {
uri,
encodedUri: ownProps.match.params.uri,
name: ownProps.match.params.name,
allow_reporting,
slim_mode,
theme,