Upgrading links sentence; multi-seed radio
This commit is contained in:
@ -7,7 +7,7 @@ import Header from '../components/Header';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import Parallax from '../components/Parallax';
|
||||
import ArtistSentence from '../components/ArtistSentence';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import Loader from '../components/Loader';
|
||||
import FollowButton from '../components/Fields/FollowButton';
|
||||
import NiceNumber from '../components/NiceNumber';
|
||||
@ -186,7 +186,7 @@ export class Album extends React.Component {
|
||||
) : null}
|
||||
{album.artists && album.artists.length > 0 ? (
|
||||
<li>
|
||||
<ArtistSentence artists={album.artists} />
|
||||
<LinksSentence items={album.artists} />
|
||||
</li>
|
||||
) : null}
|
||||
{album.release_date ? (
|
||||
|
||||
@ -7,7 +7,7 @@ import Icon from '../components/Icon';
|
||||
import Parallax from '../components/Parallax';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Dater from '../components/Dater';
|
||||
import ArtistSentence from '../components/ArtistSentence';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import Header from '../components/Header';
|
||||
import URILink from '../components/URILink';
|
||||
@ -112,24 +112,6 @@ class Queue extends React.Component {
|
||||
this.props.mopidyActions.reorderTracklist(indexes, index);
|
||||
}
|
||||
|
||||
renderQueueStats() {
|
||||
const { current_tracklist } = this.props;
|
||||
|
||||
return (
|
||||
<div className="queue-stats mid_grey-text">
|
||||
<span>
|
||||
{`${current_tracklist.length || 0} tracks`}
|
||||
</span>
|
||||
|
|
||||
{current_tracklist.length > 0 ? (
|
||||
<Dater type="total-time" data={current_tracklist} />
|
||||
) : (
|
||||
<span>0 mins</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderArtwork(image) {
|
||||
const { current_track } = this.props;
|
||||
|
||||
@ -147,7 +129,7 @@ class Queue extends React.Component {
|
||||
}
|
||||
return (
|
||||
<div className="current-track__artwork">
|
||||
<URILink type="album" uri={uri}>
|
||||
<URILink uri={uri}>
|
||||
<Thumbnail glow image={image} />
|
||||
</URILink>
|
||||
</div>
|
||||
@ -159,44 +141,44 @@ class Queue extends React.Component {
|
||||
if (!added_from_uri) return null;
|
||||
|
||||
const uri_type = helpers.uriType(added_from_uri);
|
||||
let item_uri = added_from_uri;
|
||||
let item_type = uri_type;
|
||||
const items = [];
|
||||
|
||||
// Radio nests it's seed URIs in an encoded URI format
|
||||
if (uri_type === 'radio') {
|
||||
const radio_seeds = helpers.getFromUri('seeds', added_from_uri);
|
||||
|
||||
// For now we only care about the first seed
|
||||
// TODO: Support for multiple seeds
|
||||
item_uri = radio_seeds[0];
|
||||
item_type = helpers.uriType(item_uri);
|
||||
|
||||
for (let seed of radio_seeds) {
|
||||
let item_type = helpers.uriType(seed);
|
||||
let item_library = this.props[`${item_type}s`];
|
||||
if (item_library && item_library[seed]) {
|
||||
items.push(item_library[seed]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const item_library = this.props[`${uri_type}s`];
|
||||
if (item_library && item_library[added_from_uri]) {
|
||||
items.push(item_library[added_from_uri]);
|
||||
}
|
||||
}
|
||||
|
||||
const item_library = this.props[`${item_type}s`];
|
||||
if (!item_library) return null;
|
||||
|
||||
const item = item_library[item_uri];
|
||||
if (!item) return null;
|
||||
if (items.length <= 0) return null;
|
||||
|
||||
return (
|
||||
<div className="current-track__added-from">
|
||||
<URILink
|
||||
type={item_type}
|
||||
uri={item.uri}
|
||||
uri={items[0].uri}
|
||||
className="current-track__added-from__thumbnail"
|
||||
>
|
||||
<Thumbnail
|
||||
images={item.images}
|
||||
images={items[0].images}
|
||||
size="small"
|
||||
circle={item_type === 'artist'}
|
||||
circle={helpers.uriType(items[0].uri) === 'artist'}
|
||||
/>
|
||||
</URILink>
|
||||
<div className="current-track__added-from__text">
|
||||
{'Playing from '}
|
||||
<URILink type={item_type} uri={item.uri}>
|
||||
{item.name}
|
||||
</URILink>
|
||||
{uri_type === 'radio' && <span> radio</span>}
|
||||
<LinksSentence items={items} />
|
||||
{uri_type === 'radio' && <span className="flag flag--blue">Radio</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -217,15 +199,12 @@ class Queue extends React.Component {
|
||||
|
||||
const options = (
|
||||
<span>
|
||||
{this.props.spotify_enabled ? (
|
||||
{this.props.spotify_enabled && (
|
||||
<Link className="button button--no-hover" to="/queue/radio">
|
||||
<Icon name="radio" />
|
||||
Radio
|
||||
{this.props.radio && this.props.radio.enabled ? (
|
||||
<span className="flag blue">On</span>
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
)}
|
||||
<Link className="button button--no-hover" to="/queue/history">
|
||||
<Icon name="history" />
|
||||
History
|
||||
@ -259,12 +238,12 @@ class Queue extends React.Component {
|
||||
</div>
|
||||
|
||||
{current_track ? (
|
||||
<ArtistSentence
|
||||
<LinksSentence
|
||||
className="current-track__artists"
|
||||
artists={current_track.artists}
|
||||
items={current_track.artists}
|
||||
/>
|
||||
) : (
|
||||
<ArtistSentence className="current-track__artists" />
|
||||
<LinksSentence className="current-track__artists" />
|
||||
)}
|
||||
|
||||
{this.renderAddedFrom()}
|
||||
@ -273,17 +252,14 @@ class Queue extends React.Component {
|
||||
<ul className="details">
|
||||
<li>{`${queue_tracks.length} tracks`}</li>
|
||||
<li><Dater type="total-time" data={queue_tracks} /></li>
|
||||
<li>
|
||||
<a
|
||||
onClick={(e) => {
|
||||
this.props.mopidyActions.clearTracklist();
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}}
|
||||
>
|
||||
<Icon name="delete_sweep" />
|
||||
Clear queue
|
||||
</a>
|
||||
</li>
|
||||
{queue_tracks.length > 0 && (
|
||||
<li>
|
||||
<a onClick={e => this.props.mopidyActions.clearTracklist()}>
|
||||
<Icon name="delete_sweep" />
|
||||
Clear queue
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -448,12 +448,12 @@ Advanced
|
||||
{' '}
|
||||
installed
|
||||
{this.props.pusher.version.upgrade_available ? (
|
||||
<span className="flag dark">
|
||||
<span className="flag flag--dark">
|
||||
<Icon name="cloud_download" className="blue-text" />
|
||||
Upgrade available
|
||||
</span>
|
||||
) : (
|
||||
<span className="flag dark">
|
||||
<span className="flag flag--dark">
|
||||
<Icon name="check" className="green-text" />
|
||||
Up-to-date
|
||||
</span>
|
||||
|
||||
@ -8,7 +8,7 @@ import ErrorMessage from '../components/ErrorMessage';
|
||||
import Header from '../components/Header';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import ArtistSentence from '../components/ArtistSentence';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import ArtistGrid from '../components/ArtistGrid';
|
||||
import FollowButton from '../components/Fields/FollowButton';
|
||||
import LastfmLoveButton from '../components/Fields/LastfmLoveButton';
|
||||
@ -232,13 +232,13 @@ Could not find track with URI "
|
||||
{track.album && !track.album.uri ? track.album.name : null}
|
||||
{!track.album ? 'Unknown album' : null}
|
||||
{' by '}
|
||||
<ArtistSentence artists={track.artists} />
|
||||
<LinksSentence items={track.artists} />
|
||||
</h2>
|
||||
|
||||
<ul className="details">
|
||||
{!this.props.slim_mode ? <li className="source"><Icon type="fontawesome" name={helpers.sourceIcon(this.props.uri)} /></li> : null}
|
||||
{track.date ? <li><Dater type="date" data={track.date} /></li> : null}
|
||||
{track.explicit ? <li><span className="flag dark">EXPLICIT</span></li> : null}
|
||||
{track.explicit ? <li><span className="flag flag--dark">EXPLICIT</span></li> : null}
|
||||
<li>
|
||||
{track.disc_number > 0 && <span>Disc {track.disc_number}</span>}
|
||||
{track.disc_number > 0 && track.track_number > 0 && <span>, </span>}
|
||||
|
||||
@ -5,7 +5,7 @@ import { bindActionCreators } from 'redux';
|
||||
import InputRange from 'react-input-range';
|
||||
|
||||
import Header from '../../components/Header';
|
||||
import ArtistSentence from '../../components/ArtistSentence';
|
||||
import LinksSentence from '../../components/LinksSentence';
|
||||
import ArtistGrid from '../../components/ArtistGrid';
|
||||
import AlbumGrid from '../../components/AlbumGrid';
|
||||
import TrackList from '../../components/TrackList';
|
||||
@ -23,7 +23,7 @@ import * as uiActions from '../../services/ui/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
|
||||
class Discover extends React.Component {
|
||||
class Discover extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -157,14 +157,14 @@ class Discover extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps, newState) {
|
||||
componentWillReceiveProps(newProps, newState) {
|
||||
// New seeds via URL
|
||||
if (newProps.match.params.seeds != this.props.match.params.seeds) {
|
||||
this.handleURLSeeds(newProps.match.params.seeds);
|
||||
}
|
||||
}
|
||||
|
||||
handleContextMenu(e) {
|
||||
handleContextMenu(e) {
|
||||
var uri = 'iris:discover';
|
||||
if (this.state.seeds) {
|
||||
uri += ':';
|
||||
@ -195,14 +195,14 @@ class Discover extends React.Component {
|
||||
this.props.uiActions.showContextMenu(data);
|
||||
}
|
||||
|
||||
handleURLSeeds(seeds_string = this.props.match.params.seeds) {
|
||||
handleURLSeeds(seeds_string = this.props.match.params.seeds) {
|
||||
// Rejoin if we've had to uri-encode these as strings
|
||||
// We'd need to do this if our URL has been encoded so the whole URL can become
|
||||
// it's own URI (eg iris:discover:spotify_artist_1234) where we can't use ":"
|
||||
const seeds = seeds_string.split('_').join(':').split(',');
|
||||
|
||||
for (let i = 0; i < seeds.length; i++) {
|
||||
switch (helpers.uriType(seeds[i])) {
|
||||
switch (helpers.uriType(seeds[i])) {
|
||||
case 'artist':
|
||||
this.props.spotifyActions.getArtist(seeds[i]);
|
||||
break;
|
||||
@ -263,7 +263,7 @@ class Discover extends React.Component {
|
||||
for (let i = 0; i < this.state.seeds.length; i++) {
|
||||
const uri = this.state.seeds[i];
|
||||
|
||||
switch (helpers.uriType(uri)) {
|
||||
switch (helpers.uriType(uri)) {
|
||||
case 'track':
|
||||
if (typeof (this.props.tracks[uri]) !== 'undefined') {
|
||||
seeds_objects.push(this.props.tracks[uri]);
|
||||
@ -345,7 +345,7 @@ class Discover extends React.Component {
|
||||
const addable_tunabilities = [];
|
||||
const enabled_tunabilities = [];
|
||||
for (const key in this.state.tunabilities) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
const tunability = {
|
||||
|
||||
...this.state.tunabilities[key],
|
||||
@ -380,7 +380,7 @@ class Discover extends React.Component {
|
||||
minValue={tunability.min}
|
||||
maxValue={tunability.max}
|
||||
value={tunability.value}
|
||||
onChange={(value) => this.setTunability(tunability.name, value)}
|
||||
onChange={(value) => this.setTunability(tunability.name, value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -390,7 +390,7 @@ class Discover extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderResults() {
|
||||
renderResults() {
|
||||
// Results not in
|
||||
if (!this.props.recommendations || this.props.recommendations.albums_uris === undefined || this.props.recommendations.artists_uris === undefined) {
|
||||
return <div className="content-wrapper recommendations-results" />;
|
||||
@ -479,7 +479,7 @@ class Discover extends React.Component {
|
||||
const is_loading = helpers.isLoading(this.props.load_queue, ['spotify_recommendations']);
|
||||
const addable_tunabilities = [];
|
||||
for (const key in this.state.tunabilities) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
const tunability = {
|
||||
|
||||
...this.state.tunabilities[key],
|
||||
@ -516,7 +516,7 @@ class Discover extends React.Component {
|
||||
<AddSeedField onSelect={(e, uri) => this.handleSelect(e, uri)} />
|
||||
<DropdownField className="add-properties" name="Properties" options={addable_tunabilities} no_status_icon button="default" handleChange={(val) => { this.toggleTunability(val); }} />
|
||||
<span className={`submit button button--primary button--large${is_loading ? ' button--working' : ''}`} onClick={(e) => this.getRecommendations()}>
|
||||
<Icon name="explore" />
|
||||
<Icon name="explore" />
|
||||
|
||||
Find recommendations
|
||||
</span>
|
||||
@ -551,4 +551,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Discover);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Discover);
|
||||
|
||||
@ -79,7 +79,7 @@ class EditRadio extends React.Component {
|
||||
|
||||
if (valid_seeds) {
|
||||
this.props.pusherActions.updateRadio(this.state.seeds);
|
||||
this.props.uiActions.closeModal();
|
||||
window.history.back();
|
||||
} else {
|
||||
this.setState({ error_message: 'Invalid seed URI(s)' });
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import Link from '../../components/Link';
|
||||
|
||||
import Modal from './Modal';
|
||||
import Thumbnail from '../../components/Thumbnail';
|
||||
import ArtistSentence from '../../components/ArtistSentence';
|
||||
import LinksSentence from '../../components/LinksSentence';
|
||||
import Dater from '../../components/Dater';
|
||||
import Icon from '../../components/Icon';
|
||||
import ProgressSlider from '../../components/Fields/ProgressSlider';
|
||||
@ -15,7 +15,7 @@ import * as helpers from '../../helpers';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
|
||||
class KioskMode extends React.Component {
|
||||
class KioskMode extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
@ -73,7 +73,7 @@ class KioskMode extends React.Component {
|
||||
<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 ? <ArtistSentence nolinks artists={this.props.current_track.artists} /> : <ArtistSentence /> }
|
||||
{ this.props.current_track ? <LinksSentence nolinks items={this.props.current_track.artists} /> : <LinksSentence /> }
|
||||
</div>
|
||||
|
||||
<div className="progress-wrapper">
|
||||
@ -95,4 +95,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(KioskMode);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(KioskMode);
|
||||
|
||||
Reference in New Issue
Block a user