From 6216e7dfa7abe9152ab003a378cb44e12e799415 Mon Sep 17 00:00:00 2001 From: Chris Garrity Date: Mon, 1 Jul 2019 10:20:37 -0400 Subject: [PATCH] improve touch interactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Play button is larger (easier to touch). Can both start and stop sounds. Sound doesn’t restart on mouseEnter if the sound is already playing. Sound stops if you move off play button Missing: stop button does not revert to play button when the sound finishes. --- src/components/library-item/icon--stop.svg | 28 ++++++++++++++++++++ src/components/library-item/library-item.css | 4 +-- src/components/library-item/library-item.jsx | 11 +++++--- src/components/library/library.jsx | 17 +++++++++--- src/containers/library-item.jsx | 10 +++++++ 5 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 src/components/library-item/icon--stop.svg diff --git a/src/components/library-item/icon--stop.svg b/src/components/library-item/icon--stop.svg new file mode 100644 index 000000000..53837e30c --- /dev/null +++ b/src/components/library-item/icon--stop.svg @@ -0,0 +1,28 @@ + + + + stop-playback + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/library-item/library-item.css b/src/components/library-item/library-item.css index 7b7079441..760153eae 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 3101e4279..f63f92d39 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 {
) : 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 3be73b34c..0a86c26db 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 3ffa81485..75f6b2998 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