From 6216e7dfa7abe9152ab003a378cb44e12e799415 Mon Sep 17 00:00:00 2001
From: Chris Garrity <chrisg@media.mit.edu>
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   | Bin 0 -> 1887 bytes
 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, 33 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 0000000000000000000000000000000000000000..53837e30c9f0e93279855f364db975e17ae9386f
GIT binary patch
literal 1887
zcmbVNTW{Jh6n^io@LWx5r8##fK?&8mse7tgjrIqG#3UXejvR-}zu&Q)Kq#<>8HDZQ
z<L}%)AEL+Ix<nf)8pf*_yOx6ytx}$`Dv$BU`!ktf)X1dDl9E?6#udkpvzw^d<Y>z>
zS;Tnc)jNy|%JM??yA7k;C%%iZgB&#S;ERVwT#UeM)x@}vvYy)ZcDuE<zQsjudyeDS
z0N<%hcO|P<mlWMF3~haiXEz8&^o0=gi&j)5l8Y&tuc%B56!?~h?)=ahhxdq}fyD(c
z=$a*6xK_&7c4O`k(m_flOFC;LuSs1d`$dwjBHIX!&5Snb?1!L<q#0yH7M)ouvh`7~
zwQLNcc2v+*B9_ItPGmt;HXu_N?e%Y$)*v`0Rjmc+1b7zN>hb_<$x2CuLLjbhjlXJ`
ze%WEU-h<`CNnfOXZ|;6nOhPI6;twD{@wQUMhw5SNqR}B<mt^I?8qt!za8Vb$<oO<n
zBx5aLK$&@M@*m@jm5>!c0b<R0D^mKstcwIfp-o!?SDGTp_;y}H_OjO&qHtAwL*Qea
zoz2(fvY`@XCSjS$m@;qy>ysUGb!f*(&TRbP>zX%AQti0`KDi8X?^8&}sCg?tM|g5s
zM|d!C!Fb8VOCkl^p-ob@6tb!wk^Wd-IC1>YbH|X5qjUt4(RecU2U7Q-V7UmmCHFPF
z-n9lcCAkn-=i9-9qjyji%`+oW-0le-<(ejMNlq1$8!7lo_lXKhZ+4`oAx3~wswSci
z)tZR51Z}#Z70<E($2!=bv{|XgM~Lf9oZW+`LJ>*TEV)?6ST7aJ?#S2;EodDuz9HfV
zqi%CQz|<Tv?#?BxNdT~K@T!6C<Xy1!6=>&x8+cbx2gnML*yJ}&xyWEK2luZ4k3IhY
z?K=<uz#ibA^rBC}DYbq?Z9}_sFG^@zUA}ppq)fuQfm)f8#<&&b-L2UW?;g65YPr)w
z&}EEoyA}o10Kg+5dNchzFn9Z`$HfBwAGYq7J+lt*XXH{%!5W!9s^-3v`p3=}!1_uj
Z?ITfhWasCho(WF`hmBrD>Mv||^B1Fm6_Ee{

literal 0
HcmV?d00001

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 {
                     <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 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
-- 
GitLab