Kiosk mode lyrics

This commit is contained in:
James Barnsley
2020-02-15 21:45:29 +13:00
parent 96419046ff
commit 2928eea8f9
12 changed files with 19882 additions and 27579 deletions

View File

@ -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>}

View File

@ -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({

View File

@ -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>
);
}

View File

@ -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);

View File

@ -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>
);