Kiosk mode lyrics
This commit is contained in:
@ -275,9 +275,9 @@ class PlaybackControls extends React.Component {
|
||||
onTouchEnd={(e) => touch_enabled && this.handleTouchEnd(e)}
|
||||
tabIndex="-1"
|
||||
>
|
||||
<Link className="thumbnail-wrapper" to="/kiosk-mode" tabIndex="-1">
|
||||
<div className="thumbnail-wrapper">
|
||||
<Thumbnail size="small" images={images} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="text">
|
||||
<div className="title">
|
||||
{current_track ? current_track.name : <span>-</span>}
|
||||
|
||||
@ -2285,6 +2285,7 @@ const MopidyMiddleware = (function () {
|
||||
|
||||
const track = { ...response[0] };
|
||||
store.dispatch(coreActions.trackLoaded(track));
|
||||
store.dispatch(mopidyActions.getImages('tracks', [track.uri]));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
@ -2309,7 +2310,7 @@ const MopidyMiddleware = (function () {
|
||||
for (const uri in response) {
|
||||
if (response.hasOwnProperty(uri)) {
|
||||
let images = response[uri];
|
||||
images = helpers.digestMopidyImages(store.getState().mopidy, images);
|
||||
images = helpers.formatImages(helpers.digestMopidyImages(store.getState().mopidy, images));
|
||||
|
||||
if (images && images.length > 0) {
|
||||
records.push({
|
||||
|
||||
@ -127,9 +127,9 @@ class Queue extends React.Component {
|
||||
}
|
||||
return (
|
||||
<div className="current-track__artwork">
|
||||
<URILink uri={uri}>
|
||||
<Link to="/kiosk-mode" >
|
||||
<Thumbnail glow image={image} />
|
||||
</URILink>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -7,17 +7,36 @@ import Link from '../../components/Link';
|
||||
import Modal from './Modal';
|
||||
import Thumbnail from '../../components/Thumbnail';
|
||||
import LinksSentence from '../../components/LinksSentence';
|
||||
import Dater from '../../components/Dater';
|
||||
import Loader from '../../components/Loader';
|
||||
import Icon from '../../components/Icon';
|
||||
import ProgressSlider from '../../components/Fields/ProgressSlider';
|
||||
|
||||
import * as helpers from '../../helpers';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as geniusActions from '../../services/genius/actions';
|
||||
|
||||
const LyricsScroller = ({ content = '', time_position = 1, duration = 100 }) => {
|
||||
const percent = ((time_position / duration) * 110).toFixed(4);
|
||||
|
||||
return (
|
||||
<div className="lyrics">
|
||||
<div
|
||||
className="lyrics__content"
|
||||
dangerouslySetInnerHTML={{ __html: content }}
|
||||
style={{ transform: `translateY(-${percent}%)` }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
class KioskMode extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showLyrics: false,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -27,6 +46,10 @@ class KioskMode extends React.Component {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.props.current_track && nextProps.current_track) {
|
||||
this.setWindowTitle(nextProps.current_track);
|
||||
|
||||
if (this.state.showLyrics && nextProps.genius_authorized && nextProps.current_track && nextProps.current_track.artists && !nextProps.current_track.lyrics_results) {
|
||||
this.props.geniusActions.findTrackLyrics(nextProps.current_track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,33 +76,96 @@ class KioskMode extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
toggleLyrics = () => {
|
||||
const {
|
||||
showLyrics,
|
||||
} = this.state;
|
||||
|
||||
this.setState({ showLyrics: !showLyrics });
|
||||
if (
|
||||
!showLyrics
|
||||
&& this.props.genius_authorized
|
||||
&& this.props.current_track
|
||||
&& this.props.current_track.artists
|
||||
&& !this.props.current_track.lyrics_results) {
|
||||
this.props.geniusActions.findTrackLyrics(this.props.current_track);
|
||||
}
|
||||
}
|
||||
|
||||
renderLyrics = () => {
|
||||
if (helpers.isLoading(this.props.load_queue, ['genius_'])) {
|
||||
return (
|
||||
<div className="lyrics">
|
||||
<Loader loading />
|
||||
</div>
|
||||
);
|
||||
} if (this.props.current_track && this.props.current_track.lyrics) {
|
||||
return (
|
||||
<LyricsScroller
|
||||
content={this.props.current_track.lyrics}
|
||||
time_position={this.props.time_position}
|
||||
duration={this.props.current_track ? this.props.current_track.duration : null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
renderPlayButton() {
|
||||
let button = <button className="control play" onClick={() => this.props.mopidyActions.play()}><Icon name="play_circle_filled" type="material" /></button>;
|
||||
if (this.props.play_state == 'playing') {
|
||||
button = <button className="control play" onClick={() => this.props.mopidyActions.pause()}><Icon name="pause_circle_filled" type="material" /></button>;
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
showLyrics,
|
||||
} = this.state;
|
||||
if (this.props.current_track && this.props.current_track.images) {
|
||||
var { images } = this.props.current_track;
|
||||
} else {
|
||||
var images = [];
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal className="modal--kiosk-mode">
|
||||
const extraControls = (
|
||||
<div className="control" onClick={this.toggleLyrics} style={showLyrics ? { opacity: 1 } : {}}>
|
||||
<Icon name="queue_music" className={showLyrics ? 'turquoise-text' : null} />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal className="modal--kiosk-mode" extraControls={extraControls}>
|
||||
<Thumbnail className="background" images={images} />
|
||||
|
||||
<div className="artwork" onClick={(e) => this.togglePlay(e)}>
|
||||
<Thumbnail images={images} />
|
||||
{this.props.play_state == 'playing' ? <Icon name="pause_circle_filled" /> : <Icon name="play_circle_filled" />}
|
||||
</div>
|
||||
|
||||
<div className="player">
|
||||
<div className="current-track">
|
||||
<div className="title">{ this.props.current_track ? this.props.current_track.name : <span>-</span> }</div>
|
||||
{ this.props.current_track ? <LinksSentence nolinks items={this.props.current_track.artists} /> : <LinksSentence /> }
|
||||
<div className={`track-info track-info--${showLyrics ? 'with' : 'without'}-lyrics`}>
|
||||
<div className="artwork">
|
||||
<Thumbnail images={images} />
|
||||
</div>
|
||||
|
||||
<div className="progress-wrapper">
|
||||
<ProgressSlider />
|
||||
<div className="player">
|
||||
<div className="current-track">
|
||||
<div className="title">{ this.props.current_track ? this.props.current_track.name : <span>-</span> }</div>
|
||||
{ this.props.current_track ? <LinksSentence nolinks items={this.props.current_track.artists} /> : <LinksSentence /> }
|
||||
</div>
|
||||
|
||||
<div className="player__controls">
|
||||
<button className="control previous" onClick={() => this.props.mopidyActions.previous()}>
|
||||
<Icon name="navigate_before" type="material" />
|
||||
</button>
|
||||
{ this.renderPlayButton() }
|
||||
<button className="control next" onClick={() => this.props.mopidyActions.next()}>
|
||||
<Icon name="navigate_next" type="material" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="progress-wrapper">
|
||||
<ProgressSlider />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{showLyrics && this.renderLyrics()}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@ -88,11 +174,15 @@ class KioskMode extends React.Component {
|
||||
const mapStateToProps = (state) => ({
|
||||
play_state: state.mopidy.play_state,
|
||||
current_track: (state.core.current_track && state.core.tracks[state.core.current_track.uri] !== undefined ? state.core.tracks[state.core.current_track.uri] : null),
|
||||
time_position: state.mopidy.time_position,
|
||||
load_queue: state.ui.load_queue,
|
||||
genius_authorized: state.genius.authorization,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
geniusActions: bindActionCreators(geniusActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(KioskMode);
|
||||
|
||||
@ -20,24 +20,27 @@ class Modal extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let className = 'modal';
|
||||
if (this.props.className) {
|
||||
className += ` ${this.props.className}`;
|
||||
}
|
||||
const {
|
||||
extraControls = null,
|
||||
noclose = false,
|
||||
children,
|
||||
className = '',
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={`modal ${className}`}>
|
||||
|
||||
<div className="controls">
|
||||
{this.props.noclose ? null : (
|
||||
{!noclose && (
|
||||
<div className="control close" onClick={(e) => window.history.back()}>
|
||||
<Icon name="close" className="white" />
|
||||
</div>
|
||||
) }
|
||||
)}
|
||||
{extraControls}
|
||||
</div>
|
||||
|
||||
<div className="content">
|
||||
{this.props.children}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user