diff --git a/src/components/library-item/icon--stop.svg b/src/components/library-item/icon--stop.svg new file mode 100644 index 0000000000000000000000000000000000000000..53837e30c9f0e93279855f364db975e17ae9386f Binary files /dev/null and b/src/components/library-item/icon--stop.svg differ diff --git a/src/components/library-item/library-item.css b/src/components/library-item/library-item.css index 7b7079441b12ffbfcf91a12ac81d030c57f92b0b..760153eaedebf041aca9d35e60bf9450056ce8de 100644 --- a/src/components/library-item/library-item.css +++ b/src/components/library-item/library-item.css @@ -208,8 +208,8 @@ justify-content: center; overflow: hidden; /* Mask the icon animation */ - width: 1.5rem; - height: 1.5rem; + width: 2.5rem; + height: 2.5rem; background-color: $sound-primary; color: $ui-white; border-radius: 50%; diff --git a/src/components/library-item/library-item.jsx b/src/components/library-item/library-item.jsx index 3101e4279ff0171b985da24bf2b474142315983f..f63f92d39e45bc30fff1902fc306ef558990abc0 100644 --- a/src/components/library-item/library-item.jsx +++ b/src/components/library-item/library-item.jsx @@ -9,9 +9,11 @@ import classNames from 'classnames'; import bluetoothIconURL from './bluetooth.svg'; import internetConnectionIconURL from './internet-connection.svg'; import playIcon from './icon--play.svg'; +import stopIcon from './icon--stop.svg'; const preventClick = e => { e.stopPropagation(); + e.preventDefault(); }; /* eslint-disable react/prefer-stateless-function */ @@ -141,15 +143,14 @@ class LibraryItemComponent extends React.PureComponent { <div aria-label="Play" className={styles.playButton} - role="button" - tabIndex="0" onClick={preventClick} - onMouseDown={this.props.onPlay} + onMouseDown={this.props.isPlaying ? this.props.onStop : this.props.onPlay} + onMouseLeave={this.props.isPlaying ? this.props.onStop : null} > <img className={styles.playIcon} draggable={false} - src={playIcon} + src={this.props.isPlaying ? stopIcon : playIcon} /> </div> ) : null} @@ -174,6 +175,7 @@ LibraryItemComponent.propTypes = { iconURL: PropTypes.string, insetIconURL: PropTypes.string, internetConnectionRequired: PropTypes.bool, + isPlaying: PropTypes.bool, name: PropTypes.oneOfType([ PropTypes.string, PropTypes.node @@ -185,6 +187,7 @@ LibraryItemComponent.propTypes = { onMouseEnter: PropTypes.func.isRequired, onMouseLeave: PropTypes.func.isRequired, onPlay: PropTypes.func.isRequired, + onStop: PropTypes.func.isRequired, showPlayButton: PropTypes.bool }; diff --git a/src/components/library/library.jsx b/src/components/library/library.jsx index 3be73b34c8b9425c0630a55fa22f9802549e69cd..0a86c26dbff2f94f6624c9ff220fa29027af724b 100644 --- a/src/components/library/library.jsx +++ b/src/components/library/library.jsx @@ -43,7 +43,7 @@ class LibraryComponent extends React.Component { 'setFilteredDataRef' ]); this.state = { - selectedItem: null, + playingItem: null, filterQuery: '', selectedTag: ALL_TAG.tag, loaded: false @@ -75,10 +75,20 @@ class LibraryComponent extends React.Component { }); } handleMouseEnter (id) { - if (this.props.onItemMouseEnter) this.props.onItemMouseEnter(this.getFilteredData()[id]); + console.log('Library MouseEnter id:', id, ', playingItem: ', this.state.playingItem); + // don't restart if mouse over already playing item + if (this.props.onItemMouseEnter && this.state.playingItem !== id) { + this.setState({ + playingItem: id + }, this.props.onItemMouseEnter(this.getFilteredData()[id])); + } } handleMouseLeave (id) { - if (this.props.onItemMouseLeave) this.props.onItemMouseLeave(this.getFilteredData()[id]); + if (this.props.onItemMouseLeave) { + this.setState({ + playingItem: null + }, this.props.onItemMouseLeave(this.getFilteredData()[id])); + } } handleFilterChange (event) { this.setState({ @@ -185,6 +195,7 @@ class LibraryComponent extends React.Component { id={index} insetIconURL={dataItem.insetIconURL} internetConnectionRequired={dataItem.internetConnectionRequired} + isPlaying={this.state.playingItem === index} key={typeof dataItem.name === 'string' ? dataItem.name : dataItem.rawURL} name={dataItem.name} showPlayButton={this.props.showPlayButton} diff --git a/src/containers/library-item.jsx b/src/containers/library-item.jsx index 3ffa8148584be5a38420a35143e04970053f3332..75f6b2998ea7ec67ebbe913bd32193952f605871 100644 --- a/src/containers/library-item.jsx +++ b/src/containers/library-item.jsx @@ -16,6 +16,7 @@ class LibraryItem extends React.PureComponent { 'handleMouseEnter', 'handleMouseLeave', 'handlePlay', + 'handleStop', 'rotateIcon', 'startRotatingIcons', 'stopRotatingIcons' @@ -65,8 +66,14 @@ class LibraryItem extends React.PureComponent { } handlePlay (e) { e.stopPropagation(); // To prevent from bubbling back to handleClick + e.preventDefault(); this.props.onMouseEnter(this.props.id); } + handleStop (e) { + e.stopPropagation(); // To prevent from bubbling back to handleClick + e.preventDefault(); + this.props.onMouseLeave(this.props.id); + } startRotatingIcons () { this.rotateIcon(); this.intervalId = setInterval(this.rotateIcon, 300); @@ -109,6 +116,7 @@ class LibraryItem extends React.PureComponent { id={this.props.id} insetIconURL={this.props.insetIconURL} internetConnectionRequired={this.props.internetConnectionRequired} + isPlaying={this.props.isPlaying} name={this.props.name} showPlayButton={this.props.showPlayButton} onBlur={this.handleBlur} @@ -118,6 +126,7 @@ class LibraryItem extends React.PureComponent { onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onPlay={this.handlePlay} + onStop={this.handleStop} /> ); } @@ -144,6 +153,7 @@ LibraryItem.propTypes = { id: PropTypes.number.isRequired, insetIconURL: PropTypes.string, internetConnectionRequired: PropTypes.bool, + isPlaying: PropTypes.bool, name: PropTypes.oneOfType([ PropTypes.string, PropTypes.node