Skip to content
Snippets Groups Projects
Commit 043e31a4 authored by Chris Garrity's avatar Chris Garrity
Browse files

Refactor

* split play-button into container and component
* revised sound library tile:
  * play button in upper right
  * smaller sound icon (make the tile less loaded)
parent 91f5c491
No related branches found
No related tags found
No related merge requests found
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
...@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; ...@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Box from '../box/box.jsx'; import Box from '../box/box.jsx';
import PlayButton from '../play-button/play-button.jsx'; import PlayButton from '../../containers/play-button.jsx';
import styles from './library-item.css'; import styles from './library-item.css';
import classNames from 'classnames'; import classNames from 'classnames';
......
...@@ -73,7 +73,7 @@ class LibraryComponent extends React.Component { ...@@ -73,7 +73,7 @@ class LibraryComponent extends React.Component {
handleTagClick (tag) { handleTagClick (tag) {
if (this.state.playingItem === null) { if (this.state.playingItem === null) {
this.setState({ this.setState({
ilterQuery: '', filterQuery: '',
selectedTag: tag.toLowerCase() selectedTag: tag.toLowerCase()
}); });
} else { } else {
......
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
} }
[dir="ltr"] .play-button { [dir="ltr"] .play-button {
left: .5rem; right: .5rem;
} }
[dir="rtl"] .play-button { [dir="rtl"] .play-button {
right: .5rem; left: .5rem;
} }
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import bindAll from 'lodash.bindall';
import {defineMessages, injectIntl, intlShape} from 'react-intl'; import {defineMessages, injectIntl, intlShape} from 'react-intl';
...@@ -23,126 +22,52 @@ const messages = defineMessages({ ...@@ -23,126 +22,52 @@ const messages = defineMessages({
} }
}); });
class PlayButton extends React.Component { const PlayButtonComponent = ({
constructor (props) { className,
super(props); intl,
bindAll(this, [ isPlaying,
'handleClick', onClick,
'handleMouseDown', onMouseDown,
'handleMouseEnter', onMouseEnter,
'handleMouseLeave', onMouseLeave,
'handleTouchStart', setButtonRef,
'setButtonRef' ...props
]); }) => {
this.state = { const label = isPlaying ?
touchStarted: false intl.formatMessage(messages.stop) :
}; intl.formatMessage(messages.play);
}
getDerivedStateFromProps (props, state) {
// if touchStarted is true and it's not playing, the sound must have ended.
// reset the touchStarted state to allow the sound to be replayed
if (state.touchStarted && !props.isPlaying) {
return {
touchStarted: false
};
}
return null; // nothing changed
}
componentDidMount () {
// Touch start
this.buttonRef.addEventListener('touchstart', this.handleTouchStart);
}
componentWillUnmount () {
this.buttonRef.removeEventListener('touchstart', this.handleTouchStart);
}
handleClick (e) {
// stop the click from propagating out of the button
e.stopPropagation();
}
handleMouseDown (e) {
// prevent default (focus) on mouseDown
e.preventDefault();
if (this.props.isPlaying) {
// stop sound and reset touch state
this.props.onStop();
if (this.state.touchstarted) this.setState({touchStarted: false});
} else {
this.props.onPlay();
if (this.state.touchstarted) {
// started on touch, but now clicked mouse
this.setState({touchStarted: false});
}
}
}
handleTouchStart (e) {
if (this.props.isPlaying) {
// If playing, stop sound, and reset touch state
e.preventDefault();
this.setState({touchStarted: false});
this.props.onStop();
} else {
// otherwise start playing, and set touch state
e.preventDefault();
this.setState({touchStarted: true});
this.props.onPlay();
}
}
handleMouseEnter (e) {
// start the sound if it's not already playing
e.preventDefault();
if (!this.props.isPlaying) {
this.props.onPlay();
}
}
handleMouseLeave () {
// stop the sound unless it was started by touch
if (this.props.isPlaying && !this.state.touchstarted) {
this.props.onStop();
}
}
setButtonRef (ref) {
this.buttonRef = ref;
}
render () {
const {
className,
intl,
isPlaying,
onPlay, // eslint-disable-line no-unused-vars
onStop // eslint-disable-line no-unused-vars
} = this.props;
const label = isPlaying ?
intl.formatMessage(messages.stop) :
intl.formatMessage(messages.play);
return ( return (
<div <div
aria-label={label} aria-label={label}
className={classNames(styles.playButton, className, { className={classNames(styles.playButton, className, {
[styles.playing]: isPlaying [styles.playing]: isPlaying
})} })}
ref={this.setButtonRef} onClick={onClick}
onClick={this.handleClick} onMouseDown={onMouseDown}
onMouseDown={this.handleMouseDown} onMouseEnter={onMouseEnter}
onMouseEnter={this.handleMouseEnter} onMouseLeave={onMouseLeave}
onMouseLeave={this.handleMouseLeave} ref={setButtonRef}
> {...props}
<img >
className={styles.playIcon} <img
draggable={false} className={styles.playIcon}
src={isPlaying ? stopIcon : playIcon} draggable={false}
/> src={isPlaying ? stopIcon : playIcon}
</div> />
); </div>
} );
} };
PlayButton.propTypes = { PlayButtonComponent.propTypes = {
className: PropTypes.string, className: PropTypes.string,
intl: intlShape, intl: intlShape,
isPlaying: PropTypes.bool.isRequired, isPlaying: PropTypes.bool.isRequired,
onPlay: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired,
onStop: PropTypes.func.isRequired onMouseDown: PropTypes.func.isRequired,
onMouseEnter: PropTypes.func.isRequired,
onMouseLeave: PropTypes.func.isRequired,
setButtonRef: PropTypes.func.isRequired
}; };
export default injectIntl(PlayButton); export default injectIntl(PlayButtonComponent);
import PropTypes from 'prop-types';
import React from 'react';
import bindAll from 'lodash.bindall';
import PlayButtonComponent from '../components/play-button/play-button.jsx';
class PlayButton extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleClick',
'handleMouseDown',
'handleMouseEnter',
'handleMouseLeave',
'handleTouchStart',
'setButtonRef'
]);
this.state = {
touchStarted: false
};
}
getDerivedStateFromProps (props, state) {
// if touchStarted is true and it's not playing, the sound must have ended.
// reset the touchStarted state to allow the sound to be replayed
if (state.touchStarted && !props.isPlaying) {
return {
touchStarted: false
};
}
return null; // nothing changed
}
componentDidMount () {
// Touch start
this.buttonRef.addEventListener('touchstart', this.handleTouchStart);
}
componentWillUnmount () {
this.buttonRef.removeEventListener('touchstart', this.handleTouchStart);
}
handleClick (e) {
// stop the click from propagating out of the button
e.stopPropagation();
}
handleMouseDown (e) {
// prevent default (focus) on mouseDown
e.preventDefault();
if (this.props.isPlaying) {
// stop sound and reset touch state
this.props.onStop();
if (this.state.touchstarted) this.setState({touchStarted: false});
} else {
this.props.onPlay();
if (this.state.touchstarted) {
// started on touch, but now clicked mouse
this.setState({touchStarted: false});
}
}
}
handleTouchStart (e) {
if (this.props.isPlaying) {
// If playing, stop sound, and reset touch state
e.preventDefault();
this.setState({touchStarted: false});
this.props.onStop();
} else {
// otherwise start playing, and set touch state
e.preventDefault();
this.setState({touchStarted: true});
this.props.onPlay();
}
}
handleMouseEnter (e) {
// start the sound if it's not already playing
e.preventDefault();
if (!this.props.isPlaying) {
this.props.onPlay();
}
}
handleMouseLeave () {
// stop the sound unless it was started by touch
if (this.props.isPlaying && !this.state.touchstarted) {
this.props.onStop();
}
}
setButtonRef (ref) {
this.buttonRef = ref;
}
render () {
const {
className,
isPlaying,
onPlay, // eslint-disable-line no-unused-vars
onStop // eslint-disable-line no-unused-vars
} = this.props;
return (
<PlayButtonComponent
className={className}
isPlaying={isPlaying}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
setButtonRef={this.setButtonRef}
/>
);
}
}
PlayButton.propTypes = {
className: PropTypes.string,
isPlaying: PropTypes.bool.isRequired,
onPlay: PropTypes.func.isRequired,
onStop: PropTypes.func.isRequired
};
export default PlayButton;
...@@ -7,8 +7,8 @@ import AudioEngine from 'scratch-audio'; ...@@ -7,8 +7,8 @@ import AudioEngine from 'scratch-audio';
import LibraryComponent from '../components/library/library.jsx'; import LibraryComponent from '../components/library/library.jsx';
import soundIcon from '../components/asset-panel/icon--sound.svg'; import soundIcon from '../components/library-item/lib-icon--sound.svg';
import soundIconRtl from '../components/asset-panel/icon--sound-rtl.svg'; import soundIconRtl from '../components/library-item/lib-icon--sound-rtl.svg';
import soundLibraryContent from '../lib/libraries/sounds.json'; import soundLibraryContent from '../lib/libraries/sounds.json';
import soundTags from '../lib/libraries/sound-tags'; import soundTags from '../lib/libraries/sound-tags';
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment