Skip to content

Commit 043e31a

Browse files
committed
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)
1 parent 91f5c49 commit 043e31a

File tree

8 files changed

+181
-123
lines changed

8 files changed

+181
-123
lines changed
Lines changed: 9 additions & 0 deletions
Loading
Lines changed: 9 additions & 0 deletions
Loading

src/components/library-item/library-item.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
33
import React from 'react';
44

55
import Box from '../box/box.jsx';
6-
import PlayButton from '../play-button/play-button.jsx';
6+
import PlayButton from '../../containers/play-button.jsx';
77
import styles from './library-item.css';
88
import classNames from 'classnames';
99

src/components/library/library.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class LibraryComponent extends React.Component {
7373
handleTagClick (tag) {
7474
if (this.state.playingItem === null) {
7575
this.setState({
76-
ilterQuery: '',
76+
filterQuery: '',
7777
selectedTag: tag.toLowerCase()
7878
});
7979
} else {

src/components/play-button/play-button.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
}
3535

3636
[dir="ltr"] .play-button {
37-
left: .5rem;
37+
right: .5rem;
3838
}
3939

4040
[dir="rtl"] .play-button {
41-
right: .5rem;
41+
left: .5rem;
4242
}
Lines changed: 42 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
33
import classNames from 'classnames';
4-
import bindAll from 'lodash.bindall';
54

65
import {defineMessages, injectIntl, intlShape} from 'react-intl';
76

@@ -23,126 +22,52 @@ const messages = defineMessages({
2322
}
2423
});
2524

26-
class PlayButton extends React.Component {
27-
constructor (props) {
28-
super(props);
29-
bindAll(this, [
30-
'handleClick',
31-
'handleMouseDown',
32-
'handleMouseEnter',
33-
'handleMouseLeave',
34-
'handleTouchStart',
35-
'setButtonRef'
36-
]);
37-
this.state = {
38-
touchStarted: false
39-
};
40-
}
41-
getDerivedStateFromProps (props, state) {
42-
// if touchStarted is true and it's not playing, the sound must have ended.
43-
// reset the touchStarted state to allow the sound to be replayed
44-
if (state.touchStarted && !props.isPlaying) {
45-
return {
46-
touchStarted: false
47-
};
48-
}
49-
return null; // nothing changed
50-
}
51-
componentDidMount () {
52-
// Touch start
53-
this.buttonRef.addEventListener('touchstart', this.handleTouchStart);
54-
}
55-
componentWillUnmount () {
56-
this.buttonRef.removeEventListener('touchstart', this.handleTouchStart);
57-
}
58-
handleClick (e) {
59-
// stop the click from propagating out of the button
60-
e.stopPropagation();
61-
}
62-
handleMouseDown (e) {
63-
// prevent default (focus) on mouseDown
64-
e.preventDefault();
65-
if (this.props.isPlaying) {
66-
// stop sound and reset touch state
67-
this.props.onStop();
68-
if (this.state.touchstarted) this.setState({touchStarted: false});
69-
} else {
70-
this.props.onPlay();
71-
if (this.state.touchstarted) {
72-
// started on touch, but now clicked mouse
73-
this.setState({touchStarted: false});
74-
}
75-
}
76-
}
77-
handleTouchStart (e) {
78-
if (this.props.isPlaying) {
79-
// If playing, stop sound, and reset touch state
80-
e.preventDefault();
81-
this.setState({touchStarted: false});
82-
this.props.onStop();
83-
} else {
84-
// otherwise start playing, and set touch state
85-
e.preventDefault();
86-
this.setState({touchStarted: true});
87-
this.props.onPlay();
88-
}
89-
}
90-
handleMouseEnter (e) {
91-
// start the sound if it's not already playing
92-
e.preventDefault();
93-
if (!this.props.isPlaying) {
94-
this.props.onPlay();
95-
}
96-
}
97-
handleMouseLeave () {
98-
// stop the sound unless it was started by touch
99-
if (this.props.isPlaying && !this.state.touchstarted) {
100-
this.props.onStop();
101-
}
102-
}
103-
setButtonRef (ref) {
104-
this.buttonRef = ref;
105-
}
106-
render () {
107-
const {
108-
className,
109-
intl,
110-
isPlaying,
111-
onPlay, // eslint-disable-line no-unused-vars
112-
onStop // eslint-disable-line no-unused-vars
113-
} = this.props;
114-
const label = isPlaying ?
115-
intl.formatMessage(messages.stop) :
116-
intl.formatMessage(messages.play);
25+
const PlayButtonComponent = ({
26+
className,
27+
intl,
28+
isPlaying,
29+
onClick,
30+
onMouseDown,
31+
onMouseEnter,
32+
onMouseLeave,
33+
setButtonRef,
34+
...props
35+
}) => {
36+
const label = isPlaying ?
37+
intl.formatMessage(messages.stop) :
38+
intl.formatMessage(messages.play);
11739

118-
return (
119-
<div
120-
aria-label={label}
121-
className={classNames(styles.playButton, className, {
122-
[styles.playing]: isPlaying
123-
})}
124-
ref={this.setButtonRef}
125-
onClick={this.handleClick}
126-
onMouseDown={this.handleMouseDown}
127-
onMouseEnter={this.handleMouseEnter}
128-
onMouseLeave={this.handleMouseLeave}
129-
>
130-
<img
131-
className={styles.playIcon}
132-
draggable={false}
133-
src={isPlaying ? stopIcon : playIcon}
134-
/>
135-
</div>
136-
);
137-
}
138-
}
40+
return (
41+
<div
42+
aria-label={label}
43+
className={classNames(styles.playButton, className, {
44+
[styles.playing]: isPlaying
45+
})}
46+
onClick={onClick}
47+
onMouseDown={onMouseDown}
48+
onMouseEnter={onMouseEnter}
49+
onMouseLeave={onMouseLeave}
50+
ref={setButtonRef}
51+
{...props}
52+
>
53+
<img
54+
className={styles.playIcon}
55+
draggable={false}
56+
src={isPlaying ? stopIcon : playIcon}
57+
/>
58+
</div>
59+
);
60+
};
13961

140-
PlayButton.propTypes = {
62+
PlayButtonComponent.propTypes = {
14163
className: PropTypes.string,
14264
intl: intlShape,
14365
isPlaying: PropTypes.bool.isRequired,
144-
onPlay: PropTypes.func.isRequired,
145-
onStop: PropTypes.func.isRequired
66+
onClick: PropTypes.func.isRequired,
67+
onMouseDown: PropTypes.func.isRequired,
68+
onMouseEnter: PropTypes.func.isRequired,
69+
onMouseLeave: PropTypes.func.isRequired,
70+
setButtonRef: PropTypes.func.isRequired
14671
};
14772

148-
export default injectIntl(PlayButton);
73+
export default injectIntl(PlayButtonComponent);

src/containers/play-button.jsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import PropTypes from 'prop-types';
2+
import React from 'react';
3+
import bindAll from 'lodash.bindall';
4+
5+
import PlayButtonComponent from '../components/play-button/play-button.jsx';
6+
7+
class PlayButton extends React.Component {
8+
constructor (props) {
9+
super(props);
10+
bindAll(this, [
11+
'handleClick',
12+
'handleMouseDown',
13+
'handleMouseEnter',
14+
'handleMouseLeave',
15+
'handleTouchStart',
16+
'setButtonRef'
17+
]);
18+
this.state = {
19+
touchStarted: false
20+
};
21+
}
22+
getDerivedStateFromProps (props, state) {
23+
// if touchStarted is true and it's not playing, the sound must have ended.
24+
// reset the touchStarted state to allow the sound to be replayed
25+
if (state.touchStarted && !props.isPlaying) {
26+
return {
27+
touchStarted: false
28+
};
29+
}
30+
return null; // nothing changed
31+
}
32+
componentDidMount () {
33+
// Touch start
34+
this.buttonRef.addEventListener('touchstart', this.handleTouchStart);
35+
}
36+
componentWillUnmount () {
37+
this.buttonRef.removeEventListener('touchstart', this.handleTouchStart);
38+
}
39+
handleClick (e) {
40+
// stop the click from propagating out of the button
41+
e.stopPropagation();
42+
}
43+
handleMouseDown (e) {
44+
// prevent default (focus) on mouseDown
45+
e.preventDefault();
46+
if (this.props.isPlaying) {
47+
// stop sound and reset touch state
48+
this.props.onStop();
49+
if (this.state.touchstarted) this.setState({touchStarted: false});
50+
} else {
51+
this.props.onPlay();
52+
if (this.state.touchstarted) {
53+
// started on touch, but now clicked mouse
54+
this.setState({touchStarted: false});
55+
}
56+
}
57+
}
58+
handleTouchStart (e) {
59+
if (this.props.isPlaying) {
60+
// If playing, stop sound, and reset touch state
61+
e.preventDefault();
62+
this.setState({touchStarted: false});
63+
this.props.onStop();
64+
} else {
65+
// otherwise start playing, and set touch state
66+
e.preventDefault();
67+
this.setState({touchStarted: true});
68+
this.props.onPlay();
69+
}
70+
}
71+
handleMouseEnter (e) {
72+
// start the sound if it's not already playing
73+
e.preventDefault();
74+
if (!this.props.isPlaying) {
75+
this.props.onPlay();
76+
}
77+
}
78+
handleMouseLeave () {
79+
// stop the sound unless it was started by touch
80+
if (this.props.isPlaying && !this.state.touchstarted) {
81+
this.props.onStop();
82+
}
83+
}
84+
setButtonRef (ref) {
85+
this.buttonRef = ref;
86+
}
87+
render () {
88+
const {
89+
className,
90+
isPlaying,
91+
onPlay, // eslint-disable-line no-unused-vars
92+
onStop // eslint-disable-line no-unused-vars
93+
} = this.props;
94+
return (
95+
<PlayButtonComponent
96+
className={className}
97+
isPlaying={isPlaying}
98+
onClick={this.handleClick}
99+
onMouseDown={this.handleMouseDown}
100+
onMouseEnter={this.handleMouseEnter}
101+
onMouseLeave={this.handleMouseLeave}
102+
setButtonRef={this.setButtonRef}
103+
/>
104+
);
105+
}
106+
}
107+
108+
PlayButton.propTypes = {
109+
className: PropTypes.string,
110+
isPlaying: PropTypes.bool.isRequired,
111+
onPlay: PropTypes.func.isRequired,
112+
onStop: PropTypes.func.isRequired
113+
};
114+
115+
export default PlayButton;

src/containers/sound-library.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import AudioEngine from 'scratch-audio';
77

88
import LibraryComponent from '../components/library/library.jsx';
99

10-
import soundIcon from '../components/asset-panel/icon--sound.svg';
11-
import soundIconRtl from '../components/asset-panel/icon--sound-rtl.svg';
10+
import soundIcon from '../components/library-item/lib-icon--sound.svg';
11+
import soundIconRtl from '../components/library-item/lib-icon--sound-rtl.svg';
1212

1313
import soundLibraryContent from '../lib/libraries/sounds.json';
1414
import soundTags from '../lib/libraries/sound-tags';

0 commit comments

Comments
 (0)