Drag-and-drop support for adding to new playlist, #723

This commit is contained in:
James Barnsley
2021-05-11 20:17:28 +12:00
parent 4cc2bba1ef
commit 14600279ff
4 changed files with 65 additions and 90 deletions

View File

@ -43,7 +43,7 @@ export default class Dropzone extends React.Component {
return (
<div
className={hover ? 'dropzone hover' : 'dropzone'}
onMouseUp={handleMouseUp}
onMouseUp={() => handleMouseUp(data)}
>
<Icon name={data.icon} />
<span className="title">{ data.title }</span>

View File

@ -1,106 +1,81 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { withRouter } from 'react-router';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import Dropzone from './Dropzone';
import * as uiActions from '../../services/ui/actions';
import * as mopidyActions from '../../services/mopidy/actions';
import * as spotifyActions from '../../services/spotify/actions';
import { arrayOf } from '../../util/arrays';
import { i18n } from '../../locale';
import { encodeUri } from '../../util/format';
class Dropzones extends React.Component {
constructor(props) {
super(props);
const Dropzones = () => {
const dispatch = useDispatch();
const history = useHistory();
const {
victims,
from_uri,
active,
} = useSelector((state) => state.ui.dragger || {});
const zones = [
{
title: i18n('actions.add_to_queue'),
icon: 'play_arrow',
action: 'enqueue',
},
{
title: i18n('actions.play_next'),
icon: 'play_arrow',
action: 'enqueue_next',
},
{
title: i18n('actions.add_to_playlist'),
icon: 'playlist_add',
action: 'add_to_playlist',
accepts: ['tltrack', 'track', 'album', 'playlist', 'artist'],
},
{
title: i18n('modal.edit_playlist.create_playlist'),
icon: 'playlist_add',
action: 'create_playlist_and_add',
accepts: ['tltrack', 'track', 'album', 'playlist', 'artist'],
},
];
this._zones = [
{
title: i18n('actions.add_to_queue'),
icon: 'play_arrow',
action: 'enqueue',
},
{
title: i18n('actions.play_next'),
icon: 'play_arrow',
action: 'enqueue_next',
},
{
title: i18n('actions.add_to_playlist'),
icon: 'playlist_add',
action: 'add_to_playlist',
accepts: ['tltrack', 'track', 'album', 'playlist', 'artist'],
},
];
}
if (!active) return null;
handleMouseMove = (e) => {
const { dragger = {}, uiActions: { dragMove } } = this.props;
if (!dragger || !dragger.active) return null;
return dragMove(e);
}
handleMouseUp = (zone) => {
const {
dragger: {
victims = [],
from_uri,
},
mopidyActions: {
enqueueURIs,
},
history,
} = this.props;
const handleMouseUp = (zone) => {
const uris = arrayOf('uri', victims);
switch (zone.action) {
case 'enqueue':
enqueueURIs(uris, from_uri);
dispatch(mopidyActions.enqueueURIs(uris, from_uri));
break;
case 'enqueue_next':
enqueueURIs(uris, from_uri, true);
dispatch(mopidyActions.enqueueURIs(uris, from_uri, true));
break;
case 'add_to_playlist':
history.push(`/add-to-playlist/${encodeUri(uris.join(','))}`);
// uris
break;
case 'create_playlist_and_add':
history.push(`/playlist/create/${encodeUri(uris.join(','))}`);
break;
default:
break;
}
}
};
render = () => {
const {
dragger = {},
} = this.props;
if (!dragger || !dragger.active) return null;
return (
<div className="dropzones">
{
zones.map((zone) => (
<Dropzone
key={zone.action}
data={zone}
handleMouseUp={handleMouseUp}
/>
))
}
</div>
);
};
return (
<div className="dropzones">
{
this._zones.map((zone) => (
<Dropzone
key={zone.action}
data={zone}
handleMouseUp={() => this.handleMouseUp(zone)}
/>
))
}
</div>
);
}
}
const mapStateToProps = (state) => ({
dragger: state.ui.dragger,
});
const mapDispatchToProps = (dispatch) => ({
uiActions: bindActionCreators(uiActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch),
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Dropzones));
export default Dropzones;

View File

@ -27,6 +27,7 @@ actions:
stop: Stop
add_to_playlist: Add to playlist
add_to_library: Add to library
create_playlist_and_add: New playlist
added_tracks_to: 'Added %{count} tracks to '
remove_from_library: Remove from library
add_to_queue: Add to queue

View File

@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react';
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Link from '../../components/Link';
import Modal from './Modal';
import Thumbnail from '../../components/Thumbnail';
import LinksSentence from '../../components/LinksSentence';
@ -12,7 +11,7 @@ import * as mopidyActions from '../../services/mopidy/actions';
import * as geniusActions from '../../services/genius/actions';
import { isLoading } from '../../util/helpers';
import { i18n, I18n } from '../../locale';
import { makeItemSelector } from '../../util/selectors';
import { makeItemSelector, makeLoadingSelector } from '../../util/selectors';
const LyricsScroller = ({
content = '',
@ -33,17 +32,17 @@ const LyricsScroller = ({
const Lyrics = ({
show_lyrics,
load_queue,
time_position = null,
current_track,
}) => {
if (!show_lyrics) {
return null;
}
const loadingSelector = makeLoadingSelector(['genius_(.*)']);
const loading = useSelector(loadingSelector);
const { lyrics, duration } = current_track || {};
if (isLoading(load_queue, ['genius_'])) {
if (loading) {
return (
<div className="lyrics">
<Loader body loading />
@ -225,6 +224,6 @@ const KioskMode = () => {
/>
</Modal>
);
}
};
export default KioskMode;