2016-11-18 15:31:06 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
import React from 'react';
|
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
|
import { bindActionCreators } from 'redux';
|
2019-01-22 21:46:56 +13:00
|
|
|
import ErrorMessage from '../components/ErrorMessage';
|
|
|
|
|
import Thumbnail from '../components/Thumbnail';
|
|
|
|
|
import PlaylistGrid from '../components/PlaylistGrid';
|
|
|
|
|
import FollowButton from '../components/Fields/FollowButton';
|
|
|
|
|
import LazyLoadListener from '../components/LazyLoadListener';
|
|
|
|
|
import Parallax from '../components/Parallax';
|
2020-07-17 22:12:47 +12:00
|
|
|
import NiceNumber, { nice_number } from '../components/NiceNumber';
|
2019-09-10 06:59:44 +12:00
|
|
|
import Loader from '../components/Loader';
|
2019-01-22 21:46:56 +13:00
|
|
|
import Icon from '../components/Icon';
|
|
|
|
|
import * as coreActions from '../services/core/actions';
|
|
|
|
|
import * as uiActions from '../services/ui/actions';
|
|
|
|
|
import * as spotifyActions from '../services/spotify/actions';
|
2020-03-03 16:39:37 +13:00
|
|
|
import {
|
|
|
|
|
isLoading,
|
|
|
|
|
getFromUri,
|
|
|
|
|
sourceIcon,
|
|
|
|
|
} from '../util/helpers';
|
|
|
|
|
import { collate } from '../util/format';
|
2020-07-17 22:12:47 +12:00
|
|
|
import { i18n, I18n } from '../locale';
|
2016-11-18 15:31:06 +13:00
|
|
|
|
2019-09-10 06:59:44 +12:00
|
|
|
class User extends React.Component {
|
2019-09-05 15:36:11 +12:00
|
|
|
componentDidMount() {
|
2020-07-17 22:12:47 +12:00
|
|
|
const {
|
|
|
|
|
uri,
|
|
|
|
|
coreActions: {
|
|
|
|
|
loadUser,
|
|
|
|
|
loadUserPlaylists,
|
|
|
|
|
},
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
this.setWindowTitle();
|
2020-07-17 22:12:47 +12:00
|
|
|
loadUser(uri);
|
|
|
|
|
loadUserPlaylists(uri);
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
|
|
|
|
|
2020-03-11 20:40:20 +13:00
|
|
|
componentDidUpdate = ({
|
|
|
|
|
uri: prevUri,
|
|
|
|
|
user: prevUser,
|
|
|
|
|
}) => {
|
|
|
|
|
const {
|
|
|
|
|
uri,
|
|
|
|
|
user,
|
|
|
|
|
coreActions: {
|
|
|
|
|
loadUser,
|
|
|
|
|
loadUserPlaylists,
|
|
|
|
|
},
|
|
|
|
|
} = this.props;
|
2019-09-05 15:36:11 +12:00
|
|
|
|
2020-03-11 20:40:20 +13:00
|
|
|
if (prevUri !== uri) {
|
|
|
|
|
loadUser(uri);
|
|
|
|
|
loadUserPlaylists(uri);
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
2020-03-11 20:40:20 +13:00
|
|
|
|
|
|
|
|
if (!prevUser && user) this.setWindowTitle(user);
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
|
|
|
|
|
2020-07-17 22:12:47 +12:00
|
|
|
setWindowTitle = (user = this.props.user) => {
|
|
|
|
|
const {
|
|
|
|
|
uiActions: { setWindowTitle },
|
|
|
|
|
} = this.props;
|
2019-09-05 15:36:11 +12:00
|
|
|
if (user) {
|
2020-07-17 22:12:47 +12:00
|
|
|
setWindowTitle(i18n('user.title_window', { name: user.name }));
|
2019-09-05 15:36:11 +12:00
|
|
|
} else {
|
2020-07-17 22:12:47 +12:00
|
|
|
setWindowTitle(i18n('user.title'));
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-17 22:12:47 +12:00
|
|
|
loadMore = () => {
|
|
|
|
|
const {
|
|
|
|
|
uri,
|
|
|
|
|
spotifyActions: { getMore },
|
|
|
|
|
user: { playlists_more } = {},
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
|
|
getMore(
|
|
|
|
|
playlists_more,
|
2019-09-05 15:36:11 +12:00
|
|
|
{
|
|
|
|
|
parent_type: 'user',
|
2020-07-17 22:12:47 +12:00
|
|
|
parent_key: uri,
|
2019-09-05 15:36:11 +12:00
|
|
|
records_type: 'playlist',
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-17 22:12:47 +12:00
|
|
|
isMe = () => {
|
|
|
|
|
const {
|
|
|
|
|
uri,
|
|
|
|
|
me: { id } = {},
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
|
|
return (id && id === getFromUri('userid', uri));
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
|
|
|
|
|
2020-07-17 22:12:47 +12:00
|
|
|
render = () => {
|
|
|
|
|
const {
|
|
|
|
|
uri,
|
|
|
|
|
load_queue,
|
|
|
|
|
user: userProp,
|
|
|
|
|
playlists,
|
|
|
|
|
slim_mode,
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
|
|
const user_id = getFromUri('userid', uri);
|
2019-09-05 15:36:11 +12:00
|
|
|
|
2020-07-17 22:12:47 +12:00
|
|
|
if (!userProp) {
|
|
|
|
|
if (isLoading(load_queue, [`spotify_users/${user_id}`, `spotify_users/${user_id}/playlists/?`])) {
|
2019-09-10 06:59:44 +12:00
|
|
|
return <Loader body loading />
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<ErrorMessage type="not-found" title="Not found">
|
2019-09-10 06:59:44 +12:00
|
|
|
<p>
|
2020-07-17 22:12:47 +12:00
|
|
|
<I18n path="errors.uri_not_found" uri={uri} />
|
2019-09-05 15:36:11 +12:00
|
|
|
</p>
|
|
|
|
|
</ErrorMessage>
|
2019-09-10 06:59:44 +12:00
|
|
|
);
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
|
|
|
|
|
2020-07-17 22:12:47 +12:00
|
|
|
const user = collate(userProp, { playlists });
|
|
|
|
|
const image = user.images ? user.images.huge : null;
|
2019-09-05 15:36:11 +12:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="view user-view preserve-3d">
|
|
|
|
|
<div className="intro preserve-3d">
|
|
|
|
|
|
|
|
|
|
<Parallax image={image} blur />
|
|
|
|
|
|
|
|
|
|
<div className="liner">
|
|
|
|
|
<div className="heading">
|
|
|
|
|
|
|
|
|
|
<div className="heading__thumbnail">
|
2020-04-17 21:44:49 +12:00
|
|
|
<Thumbnail size="medium" circle canZoom image={image} type="user" />
|
2019-09-05 15:36:11 +12:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="heading__content">
|
|
|
|
|
<h1>{user.name}</h1>
|
|
|
|
|
<div className="heading__content__details">
|
|
|
|
|
<div className="actions">
|
2020-07-17 22:12:47 +12:00
|
|
|
<FollowButton
|
|
|
|
|
className="primary"
|
|
|
|
|
uri={user.uri}
|
|
|
|
|
/>
|
2019-09-05 15:36:11 +12:00
|
|
|
</div>
|
|
|
|
|
<h2>
|
|
|
|
|
<ul className="details">
|
2020-07-17 22:12:47 +12:00
|
|
|
{!slim_mode && (
|
|
|
|
|
<li className="source">
|
|
|
|
|
<Icon type="fontawesome" name={sourceIcon(user.uri)} />
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
|
|
|
|
{user.playlists_total && (
|
|
|
|
|
<li>
|
|
|
|
|
<I18n path="specs.playlists" count={nice_number(user.playlists_total)} />
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
|
|
|
|
{user.followers && (
|
|
|
|
|
<li>
|
|
|
|
|
<I18n path="specs.followers" count={nice_number(user.followers)} />
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
|
|
|
|
{this.isMe() && (
|
|
|
|
|
<li>
|
|
|
|
|
<span className="blue-text">
|
|
|
|
|
<I18n path="user.you" />
|
|
|
|
|
</span>
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
|
|
|
|
</ul>
|
2019-09-05 15:36:11 +12:00
|
|
|
</h2>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="content-wrapper">
|
|
|
|
|
<section className="grid-wrapper">
|
2020-07-17 22:12:47 +12:00
|
|
|
<h4>
|
|
|
|
|
<I18n path="playlist.title_plural" />
|
|
|
|
|
</h4>
|
2019-09-05 15:36:11 +12:00
|
|
|
<PlaylistGrid playlists={user.playlists} />
|
|
|
|
|
<LazyLoadListener
|
|
|
|
|
loadKey={user.playlists_more}
|
|
|
|
|
showLoader={user.playlists_more}
|
2020-07-17 22:12:47 +12:00
|
|
|
loadMore={this.loadMore}
|
2019-09-05 15:36:11 +12:00
|
|
|
/>
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2016-11-18 15:31:06 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mapStateToProps = (state, ownProps) => {
|
2019-09-05 15:36:11 +12:00
|
|
|
const uri = decodeURIComponent(ownProps.match.params.uri);
|
|
|
|
|
return {
|
|
|
|
|
uri,
|
|
|
|
|
me: state.spotify.me,
|
|
|
|
|
load_queue: state.ui.load_queue,
|
|
|
|
|
spotify_authorized: state.spotify.authorization,
|
|
|
|
|
playlists: state.core.playlists,
|
|
|
|
|
user: (state.core.users[uri] !== undefined ? state.core.users[uri] : false),
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
|
|
|
coreActions: bindActionCreators(coreActions, dispatch),
|
|
|
|
|
uiActions: bindActionCreators(uiActions, dispatch),
|
|
|
|
|
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(User);
|