Tracklist 'source' to contain all the meta we need for queue (avoids unnecessary remote lookups)

This commit is contained in:
James Barnsley
2021-11-28 20:37:20 +13:00
parent a59f98ff9b
commit 46f22ead84
16 changed files with 102 additions and 58 deletions

View File

@ -7,31 +7,16 @@ import {
titleCase, titleCase,
uriType, uriType,
} from '../util/helpers'; } from '../util/helpers';
import {
makeItemSelector,
makeLoadingSelector,
} from '../util/selectors';
import { loadUri } from '../services/core/actions';
export default ({ export default ({
by, by,
uri, from,
className = '', className = '',
inline, inline,
}) => { }) => {
if (!uri) return null; if (!from) return null;
const { uri, name } = from;
const dispatch = useDispatch(); const type = uriType(uri);
const from = useSelector(makeItemSelector(uri));
const loading = useSelector(makeLoadingSelector([`(.*)${uri}(.*)`]));
useEffect(() => {
if (uri && !from && !loading) {
dispatch(loadUri(uri));
}
}, []);
const type = from?.type || uriType(uri);
let link = null; let link = null;
switch (type) { switch (type) {
case 'discover': case 'discover':
@ -44,7 +29,7 @@ export default ({
case 'browse': case 'browse':
link = ( link = (
<URILink type={from?.type} uri={uri}> <URILink type={type} uri={uri}>
<I18n path="library.browse.title" /> <I18n path="library.browse.title" />
</URILink> </URILink>
); );
@ -52,7 +37,7 @@ export default ({
case 'search': case 'search':
link = ( link = (
<URILink type={from?.type} uri={uri}> <URILink type={type} uri={uri}>
<I18n path="search.title" /> <I18n path="search.title" />
</URILink> </URILink>
); );
@ -67,7 +52,7 @@ export default ({
break; break;
default: default:
link = <URILink type={type} uri={uri}>{from?.name || titleCase(type)}</URILink>; link = <URILink type={type} uri={uri}>{name || titleCase(type)}</URILink>;
} }
if (inline) { if (inline) {

View File

@ -334,12 +334,12 @@ class ContextMenu extends React.Component {
}, },
menu: { menu: {
uris, uris,
tracklist_uri, source,
} = {}, } = {},
} = this.props; } = this.props;
hideContextMenu(); hideContextMenu();
playURIs(uris, tracklist_uri); playURIs(uris, source);
} }
playPlaylist = () => { playPlaylist = () => {
@ -420,12 +420,12 @@ class ContextMenu extends React.Component {
}, },
menu: { menu: {
uris, uris,
tracklist_uri, source,
} = {}, } = {},
} = this.props; } = this.props;
hideContextMenu(); hideContextMenu();
enqueueURIs(uris, tracklist_uri, play_next); enqueueURIs(uris, source, play_next);
} }
addTracksToPlaylist = (e, playlist_uri) => { addTracksToPlaylist = (e, playlist_uri) => {

View File

@ -76,7 +76,17 @@ const SearchResults = ({
{type === 'artists' && <Grid items={results} show_source_icon mini={all} />} {type === 'artists' && <Grid items={results} show_source_icon mini={all} />}
{type === 'albums' && <Grid items={results} show_source_icon mini={all} />} {type === 'albums' && <Grid items={results} show_source_icon mini={all} />}
{type === 'playlists' && <Grid items={results} show_source_icon mini={all} />} {type === 'playlists' && <Grid items={results} show_source_icon mini={all} />}
{type === 'tracks' && <TrackList tracks={results} uri={`iris:search:${query.type}:${encodedTerm}`} show_source_icon />} {type === 'tracks' && (
<TrackList
source={{
uri: `iris:search:${query.type}:${encodedTerm}`,
name: 'Search results',
type: 'search',
}}
tracks={results}
show_source_icon
/>
)}
{/* <LazyLoadListener enabled={this.props.artists_more && spotify_search_enabled} loadMore={loadMore} /> */} {/* <LazyLoadListener enabled={this.props.artists_more && spotify_search_enabled} loadMore={loadMore} /> */}
{resultsCount > results.length && ( {resultsCount > results.length && (

View File

@ -35,7 +35,7 @@ const MiddleColumn = ({
case 'queue': { case 'queue': {
content = ( content = (
<AddedFrom <AddedFrom
uri={added_from} from={added_from}
by={added_by} by={added_by}
className="list__item__column__item list__item__column__item--added" className="list__item__column__item list__item__column__item--added"
/> />

View File

@ -11,7 +11,7 @@ import { SmartList } from './SmartList';
const TrackList = ({ const TrackList = ({
uri, uri,
track_context, source,
className = '', className = '',
show_source_icon, show_source_icon,
play_state, play_state,
@ -113,7 +113,7 @@ const TrackList = ({
dragStart( dragStart(
e, e,
track_context, source.context,
uri, uri,
nextSelectedTracks, nextSelectedTracks,
nextSelectedTracks_indexes, nextSelectedTracks_indexes,
@ -223,8 +223,8 @@ const TrackList = ({
showContextMenu({ showContextMenu({
e, e,
context: (track_context ? `${track_context}-track` : 'track'), context: (source.context ? `${source.context}-track` : 'track'),
tracklist_uri: uri, source,
items: selected_tracks_digested, items: selected_tracks_digested,
uris: selected_tracks_uris, uris: selected_tracks_uris,
indexes: selected_tracks_indexes, indexes: selected_tracks_indexes,
@ -318,7 +318,7 @@ const TrackList = ({
key += `@@${track.tlid || 'none'}`; key += `@@${track.tlid || 'none'}`;
key += `@@${track.uri}`; key += `@@${track.uri}`;
key += `@@${uri || 'none'}`; key += `@@${uri || 'none'}`;
key += `@@${track_context || 'none'}`; key += `@@${source.context || 'none'}`;
return key; return key;
} }
@ -373,7 +373,7 @@ const TrackList = ({
return ( return (
<SmartList <SmartList
className={`list list--tracks ${track_context} ${className}`} className={`list list--tracks ${source?.context} ${className}`}
items={tracks} items={tracks}
itemComponent={Track} itemComponent={Track}
itemProps={{ itemProps={{
@ -381,9 +381,9 @@ const TrackList = ({
buildTrackKey, buildTrackKey,
play_state, play_state,
show_source_icon, show_source_icon,
track_context, track_context: source?.context,
selected_tracks, selected_tracks,
can_sort: track_context === 'queue' || track_context === 'editable-playlist', can_sort: source.context === 'queue' || source.context === 'editable-playlist',
mini_zones: slim_mode || isTouchDevice(), mini_zones: slim_mode || isTouchDevice(),
handleClick: onClick, handleClick: onClick,
handleDoubleClick: onDoubleClick, handleDoubleClick: onDoubleClick,

View File

@ -327,11 +327,11 @@ export function changeTrack(tlid) {
* Playing assets * Playing assets
* */ * */
export function playURIs(uris = [], from_uri = null, shuffle = false) { export function playURIs(uris = [], from = null, shuffle = false) {
return { return {
type: 'MOPIDY_PLAY_URIS', type: 'MOPIDY_PLAY_URIS',
uris, uris,
from_uri, from,
shuffle, shuffle,
}; };
} }
@ -351,11 +351,17 @@ export function playPlaylist(uri, shuffle = false) {
}; };
} }
export function enqueueURIs(uris = [], from_uri = null, play_next = false, at_position = null, offset = 0) { export function enqueueURIs(
uris = [],
from = null,
play_next = false,
at_position = null,
offset = 0,
) {
return { return {
type: 'MOPIDY_ENQUEUE_URIS', type: 'MOPIDY_ENQUEUE_URIS',
uris, uris,
from_uri, from,
at_position, at_position,
play_next, play_next,
offset, offset,

View File

@ -988,7 +988,7 @@ const MopidyMiddleware = (function () {
.then( .then(
(response) => { (response) => {
const tlids = response.map((track) => track.tlid); const tlids = response.map((track) => track.tlid);
store.dispatch(pusherActions.addQueueMetadata(tlids, action.from_uri)); store.dispatch(pusherActions.addQueueMetadata(tlids, action.from));
// Re-run the batch checker in 100ms. This allows a small window for other server // Re-run the batch checker in 100ms. This allows a small window for other server
// requests before our next batch. A little crude but it means the server isn't // requests before our next batch. A little crude but it means the server isn't
@ -1030,7 +1030,7 @@ const MopidyMiddleware = (function () {
} }
case 'MOPIDY_PLAY_URIS': case 'MOPIDY_PLAY_URIS':
const { from_uri } = action; const { from } = action;
let urisToPlay = Object.assign([], action.uris); let urisToPlay = Object.assign([], action.uris);
if (!urisToPlay || !urisToPlay.length) { if (!urisToPlay || !urisToPlay.length) {
@ -1072,7 +1072,7 @@ const MopidyMiddleware = (function () {
for (let i = 0; i < response.length; i++) { for (let i = 0; i < response.length; i++) {
tlids.push(response[i].tlid); tlids.push(response[i].tlid);
} }
store.dispatch(pusherActions.addQueueMetadata(tlids, from_uri)); store.dispatch(pusherActions.addQueueMetadata(tlids, from));
} else { } else {
store.dispatch(coreActions.handleException( store.dispatch(coreActions.handleException(
'Mopidy: Failed to add some tracks', 'Mopidy: Failed to add some tracks',
@ -1089,7 +1089,7 @@ const MopidyMiddleware = (function () {
// this means our UI feels snappier as the first track shows up quickly // this means our UI feels snappier as the first track shows up quickly
setTimeout( setTimeout(
() => { () => {
store.dispatch(mopidyActions.enqueueURIs(urisToPlay, from_uri, null, 1)); store.dispatch(mopidyActions.enqueueURIs(urisToPlay, from, null, 1));
}, },
100, 100,
); );

View File

@ -164,11 +164,11 @@ export function toggleSidebar(new_state = 'toggle') {
return action; return action;
} }
export function dragStart(e, context, from_uri = null, victims, victims_indexes = null) { export function dragStart(e, context, source = null, victims, victims_indexes = null) {
return { return {
type: 'DRAG_START', type: 'DRAG_START',
context, context,
from_uri, source,
victims, victims,
victims_indexes, victims_indexes,
start_x: e.clientX, start_x: e.clientX,

View File

@ -217,10 +217,14 @@ const Album = () => {
</div> </div>
</h4> </h4>
<TrackList <TrackList
source={{
uri: album.uri,
name: album.name,
type: 'album',
context: 'album',
}}
className="album-track-list" className="album-track-list"
tracks={tracks} tracks={tracks}
track_context="album"
uri={album.uri}
/> />
</section> </section>

View File

@ -29,6 +29,7 @@ export default ({
const [sortField, sortReverse] = useSelector(sortSelector); const [sortField, sortReverse] = useSelector(sortSelector);
const { const {
uri, uri,
name,
tracks, tracks,
related_artists, related_artists,
} = artist; } = artist;
@ -100,7 +101,17 @@ export default ({
<div className={`top-tracks col col--w${related_artists && related_artists.length > 0 ? '70' : '100'}`}> <div className={`top-tracks col col--w${related_artists && related_artists.length > 0 ? '70' : '100'}`}>
{tracks && <h4><I18n path="artist.overview.top_tracks" /></h4>} {tracks && <h4><I18n path="artist.overview.top_tracks" /></h4>}
<div className="list-wrapper"> <div className="list-wrapper">
<TrackList className="artist-track-list" uri={uri} tracks={tracks ? tracks.slice(0, 10) : []} /> <TrackList
source={{
uri,
name,
type: 'artist',
context: 'artist',
}}
className="artist-track-list"
uri={uri}
tracks={tracks ? tracks.slice(0, 10) : []}
/>
</div> </div>
</div> </div>

View File

@ -469,7 +469,15 @@ class Recommendations extends React.Component {
</Button> </Button>
</div> </div>
</h4> </h4>
<TrackList className="discover-track-list" uri={this.uri()} tracks={tracks} /> <TrackList
source={{
uri: this.uri(),
name: 'Recommendations',
type: 'recommendations',
}}
className="discover-track-list"
tracks={tracks}
/>
</section> </section>
<div className="col col--w5" /> <div className="col col--w5" />

View File

@ -226,8 +226,12 @@ class BrowseDirectory extends React.Component {
<Subdirectories items={subdirectories} view={view} /> <Subdirectories items={subdirectories} view={view} />
<TrackList <TrackList
source={{
uri: `iris:browse:${uri}`,
name: 'Browse',
type: 'browse',
}}
tracks={tracks} tracks={tracks}
uri={`iris:browse:${uri}`}
className="library-local-track-list" className="library-local-track-list"
/> />

View File

@ -176,7 +176,12 @@ class Tracks extends React.Component {
return ( return (
<section className="content-wrapper"> <section className="content-wrapper">
<TrackList tracks={tracks} /> <TrackList
source={{
name: 'Tracks'
}}
tracks={tracks}
/>
</section> </section>
); );
} }

View File

@ -332,9 +332,13 @@ const Playlist = ({
<section className="list-wrapper no-top-padding"> <section className="list-wrapper no-top-padding">
<TrackList <TrackList
uri={playlist.uri} source={{
uri: playlist.uri,
name: playlist.name,
type: 'playlist',
context,
}}
className="playlist-track-list" className="playlist-track-list"
track_context={context}
tracks={tracks} tracks={tracks}
removeTracks={removeTracks} removeTracks={removeTracks}
reorderTracks={reorderTracks} reorderTracks={reorderTracks}

View File

@ -241,9 +241,13 @@ const Queue = ({
<section className="list-wrapper"> <section className="list-wrapper">
<TrackList <TrackList
uri="iris:queue" source={{
uri: 'iris:queue',
name: 'Queue',
type: 'queue',
context: 'queue',
}}
show_source_icon show_source_icon
track_context="queue"
className="queue-track-list" className="queue-track-list"
tracks={queue_tracks} tracks={queue_tracks}
removeTracks={onRemoveTracks} removeTracks={onRemoveTracks}

View File

@ -63,9 +63,12 @@ class QueueHistory extends React.Component {
{tracks.length > 0 && ( {tracks.length > 0 && (
<section className="content-wrapper"> <section className="content-wrapper">
<TrackList <TrackList
uri="iris:queue-history" source={{
uri: 'iris:queue-history',
name: 'Queue history',
context: 'history',
}}
className="queue-history-track-list" className="queue-history-track-list"
track_context="history"
tracks={tracks} tracks={tracks}
show_source_icon show_source_icon
/> />