import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ErrorMessage from '../components/ErrorMessage';
import Button from '../components/Button';
import TrackList from '../components/TrackList';
import Thumbnail from '../components/Thumbnail';
import PinButton from '../components/Fields/PinButton';
import { nice_number } from '../components/NiceNumber';
import { Dater, dater } from '../components/Dater';
import FollowButton from '../components/Fields/FollowButton';
import Loader from '../components/Loader';
import ContextMenuTrigger from '../components/ContextMenuTrigger';
import URILink from '../components/URILink';
import { SourceIcon } from '../components/Icon';
import DropdownField from '../components/Fields/DropdownField';
import FilterField from '../components/Fields/FilterField';
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 { uriSource } from '../util/helpers';
import { i18n, I18n } from '../locale';
import { makeItemSelector, makeLoadingSelector, getSortSelector } from '../util/selectors';
import { sortItems, applyFilter } from '../util/arrays';
import { decodeUri, encodeUri } from '../util/format';
const SORT_KEY = 'playlist_tracks';
const Actions = ({
encodedUri,
playlist: {
uri,
can_edit,
name,
in_library,
},
onPlay,
handleContextMenu,
}) => {
switch (uriSource(uri)) {
case 'm3u':
return (
);
case 'spotify':
if (can_edit) {
return (
);
}
return (
);
default:
return (
);
}
}
const Playlist = ({
loading,
loading_tracks,
slim_mode,
history,
uri,
encodedUri,
name,
playlist: playlistProp,
sortField,
sortReverse,
coreActions: {
loadPlaylist,
reorderPlaylistTracks,
removeTracksFromPlaylist,
},
uiActions: {
setSort,
setWindowTitle,
showContextMenu,
hideContextMenu,
createNotification,
},
mopidyActions: {
playPlaylist,
},
}) => {
const [playlist, setPlaylist] = useState({});
const [filter, setFilter] = useState('');
useEffect(
() => {
if (uri) loadPlaylist(uri, { full: true, name });
},
[uri],
);
useEffect(() => {
if (playlistProp && playlist && playlistProp.moved_to !== playlist.moved_to) {
history.push(`/playlist/${encodeUri(playlistProp.moved_to)}`);
}
}, [playlistProp])
useEffect(() => {
if (playlistProp) {
setWindowTitle(i18n('playlist.title_window', { name: playlistProp.name }));
} else {
setWindowTitle(i18n('playlist.title'));
}
setPlaylist(playlistProp);
}, [playlistProp]);
const handleContextMenu = (e) => showContextMenu({
e,
context: 'playlist',
items: [{ name, ...playlist }],
uris: [uri],
});
const onChangeSort = (field) => {
let reverse = false;
if (field !== null && sortField === field) {
reverse = !sortReverse;
}
setSort(SORT_KEY, field, reverse);
hideContextMenu();
};
const onPlay = () => playPlaylist(uri);
const reorderTracks = (indexes, index) => {
const { snapshot_id, tracks } = playlist;
if (sortField !== 'sort_id' || filter !== '') {
createNotification({
content: i18n('errors.cannot_reorder.title'),
description: i18n('errors.cannot_reorder.description'),
level: 'error',
});
return;
}
if (sortReverse) {
const count = tracks.length - 1;
index = count - index + 1;
indexes = indexes.map((index) => count - index);
}
reorderPlaylistTracks(uri, indexes, index, snapshot_id);
}
const removeTracks = (tracks_indexes) => {
removeTracksFromPlaylist(uri, tracks_indexes);
}
if (loading) {
return ;
}
if (!playlist) {
return (
);
}
let context = 'playlist';
if (playlist.can_edit) context = 'editable-playlist';
let tracks = playlist?.tracks || [];
if (sortField && tracks) tracks = sortItems(tracks, sortField, sortReverse);
if (filter && filter !== '') tracks = applyFilter('name', filter, tracks);
const sort_options = [
{
value: 'sort_id',
label: i18n('playlist.tracks.sort.sort_id'),
},
{
value: 'name',
label: i18n('playlist.tracks.sort.name'),
},
{
value: 'artist',
label: i18n('playlist.tracks.sort.artist'),
},
{
value: 'album',
label: i18n('playlist.tracks.sort.album'),
},
];
return (
{playlist.name}
{playlist.description && (
)}
{!slim_mode && (
-
)}
{playlist.user && (
-
{playlist.user.name}
)}
-
{!slim_mode && playlist.tracks && playlist.tracks_total > 0 && (
)}
{!slim_mode && playlist.followers !== undefined && (
-
)}
{!slim_mode && playlist.last_modified_date && (
-
)}
{loading_tracks && }
);
}
const mapStateToProps = (state, ownProps) => {
const {
ui: {
allow_reporting,
slim_mode,
theme,
} = {},
spotify: {
library_playlists: spotify_library_playlists,
authorization: spotify_authorized,
me = {},
} = {},
mopidy: {
library_playlists: local_library_playlists,
} = {},
} = state;
const uri = decodeUri(ownProps.match.params.uri);
const itemSelector = makeItemSelector(uri);
const loadingSelector = makeLoadingSelector([`(.*)${uri}(.*)`, '^((?!contains).)*$', '^((?!tracks).)*$', '^((?!followers).)*$']);
const loadingTracksSelector = makeLoadingSelector([`(.*)${uri}(.*)tracks(.*)`]);
const [sortField, sortReverse] = getSortSelector(state, SORT_KEY);
return {
uri,
encodedUri: ownProps.match.params.uri,
name: ownProps.match.params.name,
allow_reporting,
slim_mode,
theme,
loading: loadingSelector(state),
loading_tracks: loadingTracksSelector(state),
playlist: itemSelector(state),
spotify_library_playlists,
local_library_playlists,
spotify_authorized,
spotify_userid: (me && me.id) || null,
sortField,
sortReverse,
};
};
const mapDispatchToProps = (dispatch) => ({
coreActions: bindActionCreators(coreActions, dispatch),
uiActions: bindActionCreators(uiActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(Playlist);