2017-06-16 09:37:40 +12:00
import React , { PropTypes } from 'react'
import { connect } from 'react-redux'
2017-06-16 15:40:39 +12:00
import { Link } from 'react-router'
2017-06-16 09:37:40 +12:00
import { bindActionCreators } from 'redux'
2018-06-26 15:37:50 +12:00
import ProgressSlider from './Fields/ProgressSlider'
import VolumeControl from './Fields/VolumeControl'
import SnapcastVolumeControl from './Fields/SnapcastVolumeControl'
import Dater from './Dater'
import ArtistSentence from './ArtistSentence'
import Thumbnail from './Thumbnail'
import Icon from './Icon'
2017-06-16 09:37:40 +12:00
2018-06-26 15:37:50 +12:00
import * as helpers from '../helpers'
import * as uiActions from '../services/ui/actions'
import * as coreActions from '../services/core/actions'
import * as mopidyActions from '../services/mopidy/actions'
2017-06-16 09:37:40 +12:00
class PlaybackControls extends React . Component {
2017-10-10 13:05:28 +13:00
constructor ( props ) {
2017-06-22 08:59:40 +12:00
super ( props )
2018-06-30 21:37:55 +12:00
this . stream = null ;
2017-06-22 08:59:40 +12:00
this . state = {
expanded : false
}
2017-06-16 09:37:40 +12:00
}
2018-06-30 21:37:55 +12:00
componentDidMount ( ) {
if ( this . props . http _streaming _enabled ) {
this . playStream ( ) ;
}
}
playStream ( props = this . props ) {
if ( ! this . stream ) {
this . stream = new Audio ( ) ;
} else {
this . stream . src = null ;
}
if ( ! props . current _track || ! props . http _streaming _enabled || ! props . http _streaming _url ) {
return false ;
}
var url = props . http _streaming _url + "?cache_buster=" + props . current _track . uri ;
console . log ( "Playing stream: " + url ) ;
this . stream . src = url ;
this . stream . play ( ) ;
}
componentWillReceiveProps ( nextProps ) {
if ( ! this . props . current _track && nextProps . current _track ||
this . props . current _track && nextProps . current _track && this . props . current _track . uri !== nextProps . current _track . uri ) {
this . playStream ( nextProps ) ;
}
}
2017-06-16 09:37:40 +12:00
renderPlayButton ( ) {
2018-05-15 21:30:57 +12:00
var button = < a className = "control play" onClick = { ( ) => this . props . mopidyActions . play ( ) } > < Icon name = "play_circle_filled" type = "material" / > < / a >
2017-10-10 13:05:28 +13:00
if ( this . props . play _state == 'playing' ) {
2018-05-15 21:30:57 +12:00
button = < a className = "control play" onClick = { ( ) => this . props . mopidyActions . pause ( ) } > < Icon name = "pause_circle_filled" type = "material" / > < / a >
2017-06-16 09:37:40 +12:00
}
return button ;
}
renderConsumeButton ( ) {
2018-05-15 21:30:57 +12:00
var button = < a className = "control has-tooltip" onClick = { ( ) => this . props . mopidyActions . setConsume ( true ) } > < Icon name = "restaurant" type = "material" / > < span className = "tooltip" > Consume < / s p a n > < / a >
2017-10-10 13:05:28 +13:00
if ( this . props . consume ) {
2018-05-15 21:30:57 +12:00
button = < a className = "control active has-tooltip" onClick = { ( ) => this . props . mopidyActions . setConsume ( false ) } > < Icon name = "restaurant" type = "material" / > < span className = "tooltip" > Consume < / s p a n > < / a >
2017-06-16 09:37:40 +12:00
}
return button ;
}
renderRandomButton ( ) {
2018-05-15 21:30:57 +12:00
var button = < a className = "control has-tooltip" onClick = { ( ) => this . props . mopidyActions . setRandom ( true ) } > < Icon name = "shuffle" type = "material" / > < span className = "tooltip" > Shuffle < / s p a n > < / a >
2017-10-10 13:05:28 +13:00
if ( this . props . random ) {
2018-05-15 21:30:57 +12:00
button = < a className = "control active has-tooltip" onClick = { ( ) => this . props . mopidyActions . setRandom ( false ) } > < Icon name = "shuffle" type = "material" / > < span className = "tooltip" > Shuffle < / s p a n > < / a >
2017-06-16 09:37:40 +12:00
}
return button ;
}
renderRepeatButton ( ) {
2018-05-15 21:30:57 +12:00
var button = < a className = "control has-tooltip" onClick = { ( ) => this . props . mopidyActions . setRepeat ( true ) } > < Icon name = "repeat" / > < span className = "tooltip" > Repeat < / s p a n > < / a >
2017-10-10 13:05:28 +13:00
if ( this . props . repeat ) {
2018-05-15 21:30:57 +12:00
button = < a className = "control active has-tooltip" onClick = { ( ) => this . props . mopidyActions . setRepeat ( false ) } > < Icon name = "repeat" / > < span className = "tooltip" > Repeat < / s p a n > < / a >
2017-06-16 09:37:40 +12:00
}
return button ;
}
2017-06-22 09:22:10 +12:00
handleThumbnailClick ( e ) {
e . preventDefault ( ) ;
2017-10-09 21:08:27 +13:00
this . props . uiActions . openModal ( 'kiosk_mode' ) ;
2017-06-22 09:22:10 +12:00
}
2017-06-16 09:37:40 +12:00
render ( ) {
2017-07-15 23:49:17 +12:00
var images = false
2017-08-03 15:26:54 +12:00
if ( this . props . current _track && this . props . current _track . images ) {
images = this . props . current _track . images
2017-06-16 09:37:40 +12:00
}
return (
2017-06-22 08:59:40 +12:00
< div className = { ( this . state . expanded ? "expanded playback-controls" : "playback-controls" ) } >
2018-02-01 08:52:15 +13:00
2018-04-12 15:55:39 +12:00
{ this . props . next _track && this . props . next _track . images ? < Thumbnail className = "hide" size = "large" images = { this . props . next _track . images } / > : null }
2017-06-16 09:37:40 +12:00
2017-07-26 15:24:18 +12:00
< div className = "current-track" >
2017-06-22 09:22:10 +12:00
< div className = "thumbnail-wrapper" onClick = { e => this . handleThumbnailClick ( e ) } >
< Thumbnail size = "small" images = { images } / >
< / d i v >
2017-06-16 09:37:40 +12:00
< div className = "title" >
{ this . props . current _track ? this . props . current _track . name : < span > - < / s p a n > }
< / d i v >
< div className = "artist" >
2017-07-26 15:24:18 +12:00
{ this . props . current _track ? < ArtistSentence artists = { this . props . current _track . artists } / > : < ArtistSentence / > }
2017-06-16 09:37:40 +12:00
< / d i v >
2017-07-26 15:24:18 +12:00
< / d i v >
2017-06-16 09:37:40 +12:00
< section className = "playback" >
2017-06-22 08:59:40 +12:00
< a className = "control previous" onClick = { ( ) => this . props . mopidyActions . previous ( ) } >
2018-05-15 21:30:57 +12:00
< Icon name = "skip_previous" type = "material" / >
2017-06-16 09:37:40 +12:00
< / a >
{ this . renderPlayButton ( ) }
2017-06-22 08:59:40 +12:00
< a className = "control stop" onClick = { ( ) => this . props . mopidyActions . stop ( ) } >
2018-05-15 21:30:57 +12:00
< Icon name = "stop" type = "material" / >
2017-06-16 09:37:40 +12:00
< / a >
2017-06-22 08:59:40 +12:00
< a className = "control next" onClick = { ( ) => this . props . mopidyActions . next ( ) } >
2018-05-15 21:30:57 +12:00
< Icon name = "skip_next" type = "material" / >
2017-06-16 09:37:40 +12:00
< / a >
< / s e c t i o n >
< section className = "settings" >
2017-10-21 18:45:55 +13:00
{ this . renderConsumeButton ( ) }
{ this . renderRandomButton ( ) }
{ this . renderRepeatButton ( ) }
2018-05-30 21:39:38 +12:00
{ this . props . snapcast _enabled ? < SnapcastVolumeControl / > : null }
2017-06-16 09:37:40 +12:00
< / s e c t i o n >
< section className = "progress" >
< ProgressSlider / >
< span className = "current" > { this . props . time _position ? < Dater type = "length" data = { this . props . time _position } / > : '-' } < / s p a n >
< span className = "total" > { this . props . current _track ? < Dater type = "length" data = { this . props . current _track . length } / > : '-' } < / s p a n >
< / s e c t i o n >
< section className = "volume" >
2018-03-23 16:54:56 +13:00
< VolumeControl
2018-04-19 08:05:42 +12:00
scrollWheel
2018-03-23 16:54:56 +13:00
volume = { this . props . volume }
mute = { this . props . mute }
onVolumeChange = { percent => this . props . mopidyActions . setVolume ( percent ) }
onMuteChange = { mute => this . props . mopidyActions . setMute ( mute ) }
/ >
2017-06-16 09:37:40 +12:00
< / s e c t i o n >
2017-06-22 08:59:40 +12:00
< section className = "triggers" >
2017-10-21 18:45:55 +13:00
< a className = "control expanded-controls" onClick = { ( ) => this . setState ( { expanded : ! this . state . expanded } ) } >
2018-05-16 16:50:46 +12:00
{ this . state . expanded ? < Icon name = "expand_more" type = "material" / > : < Icon name = "expand_less" type = "material" / > }
2017-06-22 08:59:40 +12:00
< / a >
2017-10-21 18:45:55 +13:00
< a className = { "control sidebar-toggle" + ( this . props . sidebar _open ? ' open' : '' ) } onClick = { ( ) => this . props . uiActions . toggleSidebar ( ) } >
2018-05-16 16:50:46 +12:00
< Icon className = "open" name = "menu" type = "material" / >
2017-10-21 18:45:55 +13:00
< / a >
2017-06-22 08:59:40 +12:00
< / s e c t i o n >
2017-06-16 09:37:40 +12:00
< / d i v >
) ;
}
}
/ * *
* Export our component
*
* We also integrate our global store , using connect ( )
* * /
const mapStateToProps = ( state , ownProps ) => {
return {
2018-05-30 21:39:38 +12:00
snapcast _enabled : state . pusher . config . snapcast _enabled ,
2018-02-02 08:39:37 +13:00
http _streaming _enabled : state . core . http _streaming _enabled ,
http _streaming _encoding : state . core . http _streaming _encoding ,
http _streaming _url : state . core . http _streaming _url ,
2017-11-17 20:25:43 +13:00
current _track : ( state . core . current _track && state . core . tracks [ state . core . current _track . uri ] !== undefined ? state . core . tracks [ state . core . current _track . uri ] : null ) ,
2018-04-12 15:55:39 +12:00
next _track : ( state . core . next _track _uri && state . core . tracks [ state . core . next _track _uri ] !== undefined ? state . core . tracks [ state . core . next _track _uri ] : null ) ,
2017-06-16 09:37:40 +12:00
radio _enabled : ( state . ui . radio && state . ui . radio . enabled ? true : false ) ,
play _state : state . mopidy . play _state ,
time _position : state . mopidy . time _position ,
consume : state . mopidy . consume ,
repeat : state . mopidy . repeat ,
2017-10-21 18:45:55 +13:00
random : state . mopidy . random ,
2018-03-23 16:54:56 +13:00
volume : state . mopidy . volume ,
mute : state . mopidy . mute ,
2017-10-21 18:45:55 +13:00
sidebar _open : state . ui . sidebar _open
2017-06-16 09:37:40 +12:00
}
}
const mapDispatchToProps = ( dispatch ) => {
return {
2018-02-05 17:04:31 +13:00
coreActions : bindActionCreators ( coreActions , dispatch ) ,
2017-06-22 09:22:10 +12:00
uiActions : bindActionCreators ( uiActions , dispatch ) ,
2017-06-16 09:37:40 +12:00
mopidyActions : bindActionCreators ( mopidyActions , dispatch )
}
}
export default connect ( mapStateToProps , mapDispatchToProps ) ( PlaybackControls )