Tracklist 'source' to contain all the meta we need for queue (avoids unnecessary remote lookups)
This commit is contained in:
@ -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) {
|
||||||
|
|||||||
@ -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) => {
|
||||||
|
|||||||
@ -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 && (
|
||||||
|
|||||||
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
@ -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" />
|
||||||
|
|||||||
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
@ -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
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user