import React, { PropTypes } from 'react' import { Link } from 'react-router' import FontAwesome from 'react-fontawesome' import ArtistSentence from './ArtistSentence' import Dater from './Dater' import URILink from './URILink' import ContextMenuTrigger from './ContextMenuTrigger' import * as helpers from '../helpers' export default class Track extends React.Component{ constructor(props){ super(props) this.state = { hover: false } this.start_position = false } handleMouseDown(e){ // Clicked a nested link (ie Artist name), so no dragging required if (e.target.tagName.toLowerCase() === 'a'){ return false; } // Only listen for left mouse clicks if (e.button === 0){ this.start_position = { x: e.pageX, y: e.pageY } // Not left click, then ensure no dragging } else { this.start_position = false } } handleMouseMove(e){ // No drag handling means NO if (this.props.handleDrag === undefined){ return false } if (this.start_position){ let start_x = this.start_position.x let start_y = this.start_position.y let threshold = 5 // Have we dragged outside of our threshold zone? if (e.pageX > start_x + threshold || e.pageX < start_x - threshold || e.pageY > start_y + threshold || e.pageY < start_y - threshold){ // Handover to parent for dragging. We can unset all our behaviour now. this.props.handleDrag(e) this.start_position = false } } } handleMouseUp(e){ // Only listen for left clicks if (e.button === 0){ if (this.props.dragger){ e.preventDefault() if (this.props.handleDrop !== undefined){ this.props.handleDrop(e); } } else { var target = $(e.target); if (!target.is('a') && target.closest('a').length <= 0){ this.props.handleSelection(e); this.start_position = false; } } // Not left click, then ensure no dragging } else { this.start_position = false; return false; } } handleTouchStart(e){ // Clicked a nested link (ie Artist name), so no dragging required if (e.target.tagName.toLowerCase() === 'a'){ return false; } this.props.handleTouchDrag(e); } handleContextMenu(e){ e.preventDefault(); e.stopPropagation(); e.cancelBubble = true; this.props.handleContextMenu(e); } render(){ if (!this.props.track){ return null; } var track = this.props.track; var className = 'list-item track'; if (this.props.selected) className += ' selected'; if (this.props.can_sort) className += ' can-sort'; if (track.type !== undefined) className += ' '+track.type; if (track.playing) className += ' playing'; if (this.state.hover) className += ' hover'; var album = '-'; if (track.album){ if (track.album.uri){ album = {track.album.name}; } else { album = {track.album.name}; } } let track_columns = []; let track_actions = []; if (track.type == 'history'){ track_columns.push( {track.name ? track.name : {track.uri}} ) track_columns.push( {helpers.uriSource(track.uri)} ) track_columns.push( {track.played_at ? ago : null} ) } else if (this.props.context == 'queue'){ if (track.added_from && track.added_by){ var type = (track.added_from ? helpers.uriType(track.added_from) : null) if (type == 'discover'){ var link = discover } else { var link = {type} } var added = {track.added_by} (from {link}) } else if (track.added_by){ var added = track.added_by } else { var added = '-' } track_columns.push( {track.name ? track.name : {track.uri}} {track.explicit ? EXPLICIT : null} ) if (this.props.show_source_icon){ track_columns.push( ) } track_columns.push( {track.artists ? : '-'} ) track_columns.push( {album} ) track_columns.push( {added} ) track_columns.push( {track.duration ? : null} ) } else { track_columns.push( {track.name ? track.name : {track.uri}} {track.explicit ? EXPLICIT : null} ) if (this.props.show_source_icon){ track_columns.push( ) } track_columns.push( {track.artists ? : '-'} ) track_columns.push( {album} ) track_columns.push( {track.duration ? : null} ) } track_actions.push( this.handleContextMenu(e)} /> ) if (this.props.mini_zones){ // Select zone handles selection events only // We use onClick to capture touch as well as mouse events in one tidy parcel track_actions.push( this.props.handleSelection(e)}> {this.props.selected ? : null} ) if (this.props.can_sort){ track_actions.push( this.handleTouchStart(e)}> ) } // No events attached directly to the track. Instead events are attached to // the appropriate select/drag zone sub-elements return (
{track_actions}
{track_columns}
) } else { return (
this.setState({hover: true})} onMouseLeave={e => this.setState({hover: false})}> {track_actions}
this.handleTouchEnd(e)} // When touch dragging is dropped on me onMouseDown={e => this.handleMouseDown(e)} // Click (or potentially a mouse drag start) onMouseMove={e => this.handleMouseMove(e)} // Any movement over me onMouseUp={e => this.handleMouseUp(e)} // End of click, or potentially a dragging drop event onDoubleClick={e => this.props.handleDoubleClick(e)} onContextMenu={e => {this.handleContextMenu(e)}}> {track_columns}
) } } }