Drag-and-drop within tracklists

This commit is contained in:
James Barnsley
2016-11-15 17:08:21 +13:00
parent ddcdc58043
commit af32551ddf
8 changed files with 81 additions and 58 deletions

View File

@ -15,6 +15,7 @@ class Dragger extends React.Component{
this.handleMouseUp = this.handleMouseUp.bind(this)
this.state = {
active: false,
position_x: 0,
position_y: 0
}
@ -30,28 +31,33 @@ class Dragger extends React.Component{
window.removeEventListener("mouseup", this.handleMouseUp, false);
}
componentWillReceiveProps( nextProps ){
if( this.props.dragger && this.props.dragger.dragging ){
this.setState( nextProps.dragger )
handleMouseMove(e){
if( !this.props.dragger ) return null;
var threshold = 10
if(
e.clientX > this.props.dragger.start_x + threshold ||
e.clientX < this.props.dragger.start_x - threshold ||
e.clientY > this.props.dragger.start_y + threshold ||
e.clientY < this.props.dragger.start_y - threshold ){
this.setState({
position_x: e.clientX,
position_y: e.clientY
})
// if not already, activate
if( !this.props.dragger.active ) this.props.uiActions.dragActive()
}
}
handleMouseMove(e){
if( !this.props.dragger || !this.props.dragger.dragging ) return null;
this.setState({
position_x: e.clientX,
position_y: e.clientY
})
}
handleMouseUp(e){
if( !this.props.dragger || !this.props.dragger.dragging ) return null;
if( !this.props.dragger ) return null;
this.props.uiActions.dragEnd( e )
}
render(){
if( !this.props.dragger || !this.props.dragger.dragging ) return null;
if( !this.props.dragger || !this.props.dragger.active ) return null;
var style = {
left: this.state.position_x,

View File

@ -36,7 +36,7 @@ class Dropzones extends React.Component{
}
handleMouseMove(e){
if( !this.props.dragger || !this.props.dragger.dragging ) return null;
if( !this.props.dragger || !this.props.dragger.active ) return null;
this.props.uiActions.dragMove( e )
}
@ -58,7 +58,7 @@ class Dropzones extends React.Component{
}
render(){
if( !this.props.dragger || !this.props.dragger.dragging ) return null
if( !this.props.dragger || !this.props.dragger.active ) return null
return (
<div className="dropzones">

View File

@ -23,11 +23,14 @@ export default class Track extends React.Component{
return this.props.handleDoubleClick(e);
}
handleDragStart(e){
handleMouseDown(e){
// if we're not selected, perform click behavior [first] << this is assumed
if( !this.props.track.selected ) this.handleClick(e)
this.props.handleMouseDown(e)
}
this.props.handleDragStart(e)
handleMouseUp(e){
this.props.handleMouseUp(e)
}
handleContextMenu(e){
@ -51,8 +54,8 @@ export default class Track extends React.Component{
return (
<div
className={className}
draggable='true'
onDragStart={ e => this.handleDragStart(e) }
onMouseDown={ e => this.handleMouseDown(e) }
onMouseUp={ e => this.handleMouseUp(e) }
onClick={ e => this.handleClick(e) }
onDoubleClick={ e => this.handleDoubleClick(e) }
onContextMenu={ e => this.handleContextMenu(e) }>

View File

@ -88,8 +88,16 @@ class TrackList extends React.Component{
this.playTracks()
}
handleDragStart(e, index){
this.props.uiActions.dragStart( e, this.props.context, this.selectedTracks() )
handleMouseDown(e, index){
var selected_tracks = this.selectedTracks()
this.props.uiActions.dragStart( e, this.props.context, selected_tracks, this.tracksIndexes(selected_tracks) )
}
handleMouseUp(e, index){
if( this.props.dragger && this.props.dragger.active ){
var indexes = this.props.dragger.victims_indexes
this.props.uiActions.reorderTracks(this.props.context, indexes, index)
}
}
handleContextMenu(e, index){
@ -173,7 +181,8 @@ class TrackList extends React.Component{
track={track}
handleDoubleClick={ e => self.handleDoubleClick(e, index)}
handleClick={ e => self.handleClick(e, index)}
handleDragStart={ e => self.handleDragStart(e, index)}
handleMouseUp={ e => self.handleMouseUp(e, index)}
handleMouseDown={ e => self.handleMouseDown(e, index)}
handleContextMenu={ e => self.handleContextMenu(e, index)} />
}
)
@ -192,6 +201,7 @@ class TrackList extends React.Component{
const mapStateToProps = (state, ownProps) => {
return {
dragger: state.ui.dragger,
current_track: state.ui.current_track,
context_menu: state.ui.context_menu
}

View File

@ -40,32 +40,45 @@ export function lazyLoading( start ){
}
}
export function dragStart( e, context, victims ){
export function dragStart( e, context, victims, victims_indexes = false ){
return {
type: 'DRAG_START',
context: context,
victims: victims,
position_x: e.clientX,
position_y: e.clientY
victims_indexes: victims_indexes,
start_x: e.clientX,
start_y: e.clientY
}
}
export function dragMove( e ){
return {
type: 'DRAG_MOVE',
position_x: e.clientX,
position_y: e.clientY,
}
}
export function dragCancel(){
return { type: 'DRAG_CANCEL' }
export function dragActive(){
return { type: 'DRAG_ACTIVE' }
}
export function dragEnd(){
return { type: 'DRAG_END' }
}
export function reorderTracks( context, indexes, destination_index ){
console.log('uiActions.reorderTracks', context, indexes, destination_index)
switch( context ){
case 'queue':
return {
type: 'MOPIDY_REORDER_TRACKLIST',
indexes: indexes,
destination_index: destination_index
}
case 'editable-playlist':
return {
type: 'SPOTIFY_REORDER_TRACKLIST',
indexes: indexes,
destination_index: destination_index
}
}
}
export function savePlaylist( uri, name, is_public = false ){
switch( helpers.uriSource( uri ) ){

View File

@ -34,36 +34,22 @@ export default function reducer(ui = {}, action){
return Object.assign({}, ui, {
dragger: {
dragging: true,
active: false,
context: action.context,
victims: action.victims,
position_x: action.position_x,
position_y: action.position_y
victims_indexes: action.victims_indexes,
start_x: action.start_x,
start_y: action.start_y
}
});
case 'DRAG_MOVE':
var dragger = Object.assign({}, ui.dragger, {
position_x: action.position_x,
position_y: action.position_y
})
case 'DRAG_ACTIVE':
var dragger = Object.assign({}, ui.dragger, { active: true })
return Object.assign({}, ui, { dragger: dragger });
case 'DRAG_END':
return Object.assign({}, ui, {
dragger: {
dragging: false,
context: false,
victims: false
}
});
case 'DRAG_CANCEL':
return Object.assign({}, ui, {
dragger: {
dragging: false,
context: false,
victims: false
}
dragger: false
});

View File

@ -106,7 +106,7 @@ class App extends React.Component{
render(){
var className = '';
if( this.props.dragger && this.props.dragger.dragging ) className += ' dragging'
if( this.props.dragger && this.props.dragger.active ) className += ' dragging'
return (
<div className={className}>

View File

@ -60,6 +60,11 @@
&.playing {
font-weight: 600;
}
:root .dragging &:hover {
border-top: 3px solid $blue;
margin-top: -3px;
}
}