Revamp of touch vs mobile selection
This commit is contained in:
@ -20,6 +20,7 @@ export default class Track extends React.Component{
|
||||
}
|
||||
|
||||
this.start_time = 0;
|
||||
this.end_time = 0;
|
||||
this.start_position = false
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ export default class Track extends React.Component{
|
||||
}
|
||||
} else {
|
||||
if (!target.is('a') && target.closest('a').length <= 0){
|
||||
this.props.handleSelection(e);
|
||||
this.props.handleClick(e);
|
||||
this.start_position = false;
|
||||
}
|
||||
}
|
||||
@ -108,41 +109,10 @@ export default class Track extends React.Component{
|
||||
var target = $(e.target);
|
||||
var timestamp = Math.floor(Date.now());
|
||||
|
||||
// Clicked a nested link (ie Artist name), so no touch intervention required
|
||||
if (target.is('a')){
|
||||
return false;
|
||||
|
||||
// We started a touchstart within 300ms ago, so handle as double-tap
|
||||
} else if ((timestamp - this.start_time) > 0 && (timestamp - this.start_time) <= 300){
|
||||
|
||||
// Update our selection. By not passing touch = true selection will work like a regular click
|
||||
this.props.handleSelection(e);
|
||||
|
||||
// Wait a moment to give Redux time to update our selected tracks
|
||||
// TODO: Use proper callback, rather than assuming a fixed period of time for store change
|
||||
setTimeout(() => {
|
||||
this.props.handleDoubleClick(e);
|
||||
},
|
||||
100
|
||||
);
|
||||
e.preventDefault();
|
||||
|
||||
// Touch-drag zone
|
||||
} else if (target.hasClass('drag-zone')){
|
||||
if (target.hasClass('drag-zone')){
|
||||
this.props.handleTouchDrag(e);
|
||||
e.preventDefault();
|
||||
|
||||
// Select zone
|
||||
} else if (target.hasClass('select-zone')){
|
||||
this.props.handleSelection(e, true);
|
||||
e.preventDefault();
|
||||
|
||||
// Touch contextable
|
||||
} else if (target.hasClass('touch-contextable')){
|
||||
|
||||
// Update our selection. By not passing touch = true selection will work like a regular click
|
||||
//this.props.handleSelection(e);
|
||||
this.handleContextMenu(e);
|
||||
}
|
||||
|
||||
// Save touch start details
|
||||
@ -170,6 +140,22 @@ export default class Track extends React.Component{
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// Context trigger
|
||||
if (target.hasClass('touch-contextable')){
|
||||
|
||||
// Update our selection. By not passing touch = true selection will work like a regular click
|
||||
//this.props.handleSelection(e);
|
||||
this.props.handleContextMenu(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// We received a touchend within 300ms ago, so handle as double-tap
|
||||
if ((timestamp - this.end_time) > 0 && (timestamp - this.end_time) <= 300){
|
||||
this.props.handleDoubleTap(e);
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Too long between touchstart and touchend
|
||||
if (this.start_time + tap_time_threshold < timestamp){
|
||||
return false;
|
||||
@ -179,15 +165,10 @@ export default class Track extends React.Component{
|
||||
this.start_position.x - tap_distance_threshold < end_position.x &&
|
||||
this.start_position.y + tap_distance_threshold > end_position.y &&
|
||||
this.start_position.y - tap_distance_threshold < end_position.y){
|
||||
this.props.handleSelection(e, true);
|
||||
this.props.handleTap(e);
|
||||
}
|
||||
}
|
||||
|
||||
handleContextMenu(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.cancelBubble = true;
|
||||
this.props.handleContextMenu(e);
|
||||
this.end_time = timestamp;
|
||||
}
|
||||
|
||||
render(){
|
||||
@ -314,7 +295,7 @@ export default class Track extends React.Component{
|
||||
}
|
||||
|
||||
track_actions.push(
|
||||
<ContextMenuTrigger key="context" onTrigger={e => this.handleContextMenu(e)} />
|
||||
<ContextMenuTrigger key="context" onTrigger={e => this.props.handleContextMenu(e)} />
|
||||
)
|
||||
|
||||
// If we're touchable, and can sort this tracklist
|
||||
@ -340,7 +321,7 @@ export default class Track extends React.Component{
|
||||
onMouseMove={e => this.handleMouseMove(e)}
|
||||
|
||||
onDoubleClick={e => this.handleDoubleClick(e)}
|
||||
onContextMenu={e => this.handleContextMenu(e)}
|
||||
onContextMenu={e => this.props.handleContextMenu(e)}
|
||||
|
||||
onTouchStart={e => this.handleTouchStart(e)}
|
||||
onTouchEnd={e => this.handleTouchEnd(e)}>
|
||||
|
||||
@ -174,14 +174,34 @@ class TrackList extends React.Component{
|
||||
this.touch_dragging_tracks_keys = false;
|
||||
}
|
||||
|
||||
handleTap(e, track_key){
|
||||
this.updateSelection(e, track_key, true);
|
||||
}
|
||||
|
||||
handleDoubleTap(e,track_key){
|
||||
this.playTracks([track_key]);
|
||||
this.updateSelection(e, track_key);
|
||||
}
|
||||
|
||||
handleClick(e, track_key){
|
||||
this.updateSelection(e, track_key);
|
||||
}
|
||||
|
||||
handleDoubleClick(e,track_key){
|
||||
if (this.props.context_menu){
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
this.playTracks();
|
||||
this.playTracks([track_key]);
|
||||
this.updateSelection(e, track_key);
|
||||
}
|
||||
|
||||
handleContextMenu(e, track_key = null){
|
||||
|
||||
// Do our best to stop any flow-on events
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.cancelBubble = true;
|
||||
|
||||
let selected_tracks = this.props.selected_tracks;
|
||||
|
||||
// Not already selected, so select it prior to triggering menu
|
||||
@ -206,7 +226,7 @@ class TrackList extends React.Component{
|
||||
this.props.uiActions.showContextMenu(data);
|
||||
}
|
||||
|
||||
handleSelection(e, track_key, touched = false){
|
||||
updateSelection(e, track_key, touched = false){
|
||||
let selected_tracks = this.props.selected_tracks;
|
||||
|
||||
if ((e.ctrlKey || e.metaKey) || touched){
|
||||
@ -264,9 +284,13 @@ class TrackList extends React.Component{
|
||||
return false;
|
||||
}
|
||||
|
||||
playTracks(){
|
||||
let selected_tracks = this.digestTracksKeys();
|
||||
let selected_tracks_indexes = helpers.arrayOf('index',selected_tracks);
|
||||
playTracks(tracks_keys = null){
|
||||
if (tracks_keys !== null){
|
||||
var selected_tracks = this.digestTracksKeys(tracks_keys);
|
||||
} else {
|
||||
var selected_tracks = this.digestTracksKeys();
|
||||
}
|
||||
var selected_tracks_indexes = helpers.arrayOf('index', selected_tracks);
|
||||
|
||||
if (selected_tracks.length <= 0){
|
||||
return this.props.uiActions.createNotification('No tracks selected', 'bad');
|
||||
@ -431,11 +455,13 @@ class TrackList extends React.Component{
|
||||
can_sort={this.props.context == 'queue' || this.props.context == 'editable-playlist'}
|
||||
selected={this.props.selected_tracks.includes(track_key)}
|
||||
dragger={this.props.dragger}
|
||||
handleSelection={(e, touched = false) => this.handleSelection(e, track_key, touched)}
|
||||
handleClick={(e) => this.handleClick(e, track_key)}
|
||||
handleDoubleClick={e => this.handleDoubleClick(e, track_key)}
|
||||
handleContextMenu={e => this.handleContextMenu(e, track_key)}
|
||||
handleDrag={e => this.handleDrag(e, track_key)}
|
||||
handleDrop={e => this.handleDrop(e, track_key)}
|
||||
handleTap={e => this.handleTap(e, track_key)}
|
||||
handleDoubleTap={e => this.handleDoubleTap(e, track_key)}
|
||||
handleTouchDrag={e => this.handleTouchDrag(e, track_key)}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -12,9 +12,18 @@ export function setSelectedTracks(keys = []){
|
||||
}
|
||||
|
||||
export function showContextMenu(data){
|
||||
if (data.e.touches){
|
||||
|
||||
// Touchend
|
||||
if (data.e.changedTouches){
|
||||
data.position_x = data.e.changedTouches[0].clientX;
|
||||
data.position_y = data.e.changedTouches[0].clientY;
|
||||
|
||||
// Touchstart
|
||||
} else if (data.e.touches){
|
||||
data.position_x = data.e.touches[0].clientX;
|
||||
data.position_y = data.e.touches[0].clientY;
|
||||
|
||||
// Click/mousedown/mouseup/etc
|
||||
} else {
|
||||
data.position_x = data.e.clientX;
|
||||
data.position_y = data.e.clientY;
|
||||
|
||||
Reference in New Issue
Block a user