From 15c1d83440367841a13de177aba2c665209d8b46 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Thu, 10 Nov 2016 16:17:10 +1300 Subject: [PATCH] Beginning Draggability --- src/js/components/ContextMenu.js | 3 - src/js/components/Dragger.js | 68 ++++++++++++++++++++++ src/js/components/Sidebar.js | 17 +++++- src/js/components/Track.js | 15 ++++- src/js/components/TrackList.js | 20 ++++--- src/js/services/localstorage/middleware.js | 2 +- src/js/services/ui/actions.js | 22 +++++++ src/js/services/ui/reducer.js | 34 +++++++++++ src/js/views/App.js | 8 ++- src/scss/app.scss | 1 + src/scss/components/_dragger.scss | 30 ++++++++++ src/scss/global/_variables.scss | 1 + 12 files changed, 205 insertions(+), 16 deletions(-) create mode 100755 src/js/components/Dragger.js create mode 100755 src/scss/components/_dragger.scss diff --git a/src/js/components/ContextMenu.js b/src/js/components/ContextMenu.js index 24a2562d..3d5d0e08 100755 --- a/src/js/components/ContextMenu.js +++ b/src/js/components/ContextMenu.js @@ -14,9 +14,6 @@ class ContextMenu extends React.Component{ super(props); } - handleClick(e){ - } - renderItems(){ var items = []; diff --git a/src/js/components/Dragger.js b/src/js/components/Dragger.js new file mode 100755 index 00000000..23eb4a4f --- /dev/null +++ b/src/js/components/Dragger.js @@ -0,0 +1,68 @@ + +import React, { PropTypes } from 'react' +import { connect } from 'react-redux' +import { bindActionCreators } from 'redux' + +import * as uiActions from '../services/ui/actions' +import * as mopidyActions from '../services/mopidy/actions' +import * as spotifyActions from '../services/spotify/actions' + +class Dragger extends React.Component{ + + constructor(props) { + super(props); + this.handleMouseMove = this.handleMouseMove.bind(this) + this.handleMouseUp = this.handleMouseUp.bind(this) + } + + componentDidMount(){ + window.addEventListener("mousemove", this.handleMouseMove, false); + window.addEventListener("mouseup", this.handleMouseUp, false); + } + + componentWillUnmount(){ + window.removeEventListener("mousemove", this.handleMouseMove, false); + window.removeEventListener("mouseup", this.handleMouseUp, false); + } + + handleMouseMove(e){ + if( !this.props.dragger || !this.props.dragger.dragging ) return null; + this.props.uiActions.dragMove( e ) + } + + handleMouseUp(e){ + if( !this.props.dragger || !this.props.dragger.dragging ) return null; + this.props.uiActions.dragEnd( e ) + } + + render(){ + if( !this.props.dragger || !this.props.dragger.dragging ) return null; + + var style = { + left: this.props.dragger.position_x, + top: this.props.dragger.position_y, + } + + return ( +
+ Dragging { this.props.dragger.victims.length } things +
+ ); + } +} + +const mapStateToProps = (state, ownProps) => { + return { + dragger: state.ui.dragger + } +} + +const mapDispatchToProps = (dispatch) => { + return { + uiActions: bindActionCreators(uiActions, dispatch), + spotifyActions: bindActionCreators(spotifyActions, dispatch), + mopidyActions: bindActionCreators(mopidyActions, dispatch) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(Dragger) \ No newline at end of file diff --git a/src/js/components/Sidebar.js b/src/js/components/Sidebar.js index 7a76449e..e564e7d2 100755 --- a/src/js/components/Sidebar.js +++ b/src/js/components/Sidebar.js @@ -18,6 +18,18 @@ class Sidebar extends React.Component{ super(props); } + renderDropzones(){ + if( !this.props.dragger || !this.props.dragger.dragging ) return null + + return ( +
+
+
Zone
+
+
+ ) + } + render(){ return ( @@ -109,7 +123,8 @@ const mapStateToProps = (state, ownProps) => { pusher_connected: state.pusher.connected, spotify_connected: state.spotify.connected, spotify_authorized: state.spotify.authorized, - current_track: state.ui.current_track + current_track: state.ui.current_track, + dragger: state.ui.dragger } } diff --git a/src/js/components/Track.js b/src/js/components/Track.js index 8e6fe59f..739e5cd4 100755 --- a/src/js/components/Track.js +++ b/src/js/components/Track.js @@ -23,6 +23,13 @@ export default class Track extends React.Component{ return this.props.handleDoubleClick(e); } + handleDragStart(e){ + // if we're not selected, perform click behavior [first] << this is assumed + if( !this.props.track.selected ) this.handleClick(e) + + this.props.handleDragStart(e) + } + handleContextMenu(e){ e.preventDefault(); @@ -44,9 +51,11 @@ export default class Track extends React.Component{ return (
this.handleDoubleClick(e) } - onClick={ (e) => this.handleClick(e) } - onContextMenu={ (e) => this.handleContextMenu(e) }> + draggable='true' + onDragStart={ e => this.handleDragStart(e) } + onClick={ e => this.handleClick(e) } + onDoubleClick={ e => this.handleDoubleClick(e) } + onContextMenu={ e => this.handleContextMenu(e) }> { this.props.track.selected ? : null } { track.name ? track.name : '-' } diff --git a/src/js/components/TrackList.js b/src/js/components/TrackList.js index ecf8e405..cdf011a8 100755 --- a/src/js/components/TrackList.js +++ b/src/js/components/TrackList.js @@ -2,11 +2,12 @@ import React, { PropTypes } from 'react' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' -import * as mopidyActions from '../services/mopidy/actions' -import * as uiActions from '../services/ui/actions' import Track from './Track' +import * as mopidyActions from '../services/mopidy/actions' +import * as uiActions from '../services/ui/actions' + class TrackList extends React.Component{ constructor(props) { @@ -81,12 +82,16 @@ class TrackList extends React.Component{ this.setState({ tracks: tracks, lastSelectedTrack: index }); } - handleDoubleClick( e, index ){ + handleDoubleClick(e, index){ if( this.props.context_menu.show ) this.props.uiActions.hideContextMenu(); this.playTracks() } - handleContextMenu( e, index ){ + handleDragStart(e, index){ + this.props.uiActions.dragStart( e, 'tltracks', this.selectedTracks() ) + } + + handleContextMenu(e, index){ var data = { selected_tracks: this.selectedTracks() } @@ -148,9 +153,10 @@ class TrackList extends React.Component{ show_source_icon={ this.props.show_source_icon } key={index+'_'+track.uri} track={track} - handleDoubleClick={(e) => self.handleDoubleClick(e, index)} - handleClick={(e) => self.handleClick(e, index)} - handleContextMenu={(e) => self.handleContextMenu(e, index)} /> + handleDoubleClick={ e => self.handleDoubleClick(e, index)} + handleClick={ e => self.handleClick(e, index)} + handleDragStart={ e => self.handleDragStart(e, index)} + handleContextMenu={ e => self.handleContextMenu(e, index)} /> } ) } diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index 71932e75..db626418 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -12,7 +12,7 @@ const localstorageMiddleware = (function(){ // append our state to a global variable. This gives us access to debug the store at any point window._store = store - console.log(action) + //console.log(action) switch( action.type ){ diff --git a/src/js/services/ui/actions.js b/src/js/services/ui/actions.js index 8a2ff1dd..1ebf1aa7 100755 --- a/src/js/services/ui/actions.js +++ b/src/js/services/ui/actions.js @@ -39,4 +39,26 @@ export function lazyLoading( start ){ } } +export function dragStart( e, context, victims ){ + return { + type: 'DRAG_START', + context: context, + victims: victims, + position_x: e.clientX, + position_y: e.clientY + } +} + +export function dragMove( e ){ + return { + type: 'DRAG_MOVE', + position_x: e.clientX, + position_y: e.clientY, + } +} + +export function dragEnd(){ + return { type: 'DRAG_END' } +} + diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js index 21828e0d..ff6012bd 100755 --- a/src/js/services/ui/reducer.js +++ b/src/js/services/ui/reducer.js @@ -23,6 +23,40 @@ export default function reducer(ui = {}, action){ return Object.assign({}, ui, { context_menu: { show: false } }); + + /** + * Dragging + **/ + + case 'DRAG_START': + return Object.assign({}, ui, { + dragger: { + dragging: true, + context: action.context, + victims: action.victims, + position_x: action.position_x, + position_y: action.position_y + } + }); + + case 'DRAG_MOVE': + var dragger = Object.assign({}, ui.dragger, { + position_x: action.position_x, + position_y: action.position_y + }) + return Object.assign({}, ui, { dragger: dragger }); + + case 'DRAG_END': + return Object.assign({}, ui, { + dragger: { + dragging: false, + context: false, + victims: false + } + }); + + + /** * Albums **/ diff --git a/src/js/views/App.js b/src/js/views/App.js index 269274cc..998e3d0a 100755 --- a/src/js/views/App.js +++ b/src/js/views/App.js @@ -7,6 +7,7 @@ import { connect } from 'react-redux' import Sidebar from '../components/Sidebar' import ContextMenu from '../components/ContextMenu' +import Dragger from '../components/Dragger' import * as uiActions from '../services/ui/actions' import * as pusherActions from '../services/pusher/actions' @@ -93,13 +94,17 @@ class App extends React.Component{ } render(){ + var className = ''; + if( this.props.dragger && this.props.dragger.dragging ) className += ' dragging' + return ( -
+
{this.props.children}
+
); } @@ -116,6 +121,7 @@ const mapStateToProps = (state, ownProps) => { mopidy_connected: state.mopidy.connected, spotify_authorized: state.spotify.authorized, play_state: state.mopidy.play_state, + dragger: state.ui.dragger, context_menu: state.ui.context_menu } } diff --git a/src/scss/app.scss b/src/scss/app.scss index e7891af4..935ea3ca 100755 --- a/src/scss/app.scss +++ b/src/scss/app.scss @@ -8,6 +8,7 @@ @import 'global/forms'; @import 'components/context-menu'; +@import 'components/dragger'; @import 'components/images'; @import 'components/icon'; @import 'components/search-form'; diff --git a/src/scss/components/_dragger.scss b/src/scss/components/_dragger.scss new file mode 100755 index 00000000..ea398ffe --- /dev/null +++ b/src/scss/components/_dragger.scss @@ -0,0 +1,30 @@ + +.dragger { + position: fixed; + left: 0; + top: 0; + z-index: 9999; + background: $blue; + color: #FFFFFF; + padding: 12px 20px; + pointer-events: none; +} + +.dropzones { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 9998; + background: rgba(25, 25, 25, 0.9); + + .zone { + margin: 15px; + padding: 50px 20px; + background: $turquoise; + color: #FFFFFF; + font-size: 16px; + text-align: center; + } +} \ No newline at end of file diff --git a/src/scss/global/_variables.scss b/src/scss/global/_variables.scss index d39c4677..09d7edc4 100755 --- a/src/scss/global/_variables.scss +++ b/src/scss/global/_variables.scss @@ -7,6 +7,7 @@ $dark_grey: #333333; $secondary_grey: #888888; $red: #cf2d2d; $green: #47af2a; +$blue: #32b5f2; @mixin one_line_text { white-space: nowrap;