Files
Iris/src/js/components/Fields/SpotifyAuthenticationFrame.js

148 lines
4.4 KiB
JavaScript
Raw Normal View History

2019-09-05 15:36:11 +12:00
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
2019-09-05 15:36:11 +12:00
import * as uiActions from '../../services/ui/actions';
import * as spotifyActions from '../../services/spotify/actions';
import { toJSON } from '../../util/format';
import { I18n, i18n } from '../../locale';
import { Button } from '../Button';
2019-09-05 15:36:11 +12:00
class SpotifyAuthenticationFrame extends React.Component {
2019-09-05 15:36:11 +12:00
constructor(props) {
super(props);
this.state = {
authorizing: false,
};
this.handleMessage = this.handleMessage.bind(this);
}
componentDidMount() {
window.addEventListener('message', this.handleMessage, false);
}
componentWillUnmount() {
window.removeEventListener('message', this.handleMessage, false);
}
handleMessage(event) {
const data = toJSON(event.data);
2019-09-05 15:36:11 +12:00
// Only digest messages relevant to us
if (data.origin != 'auth_spotify') {
return;
}
// Only allow incoming data from our authorized authenticator proxy
const authorization_domain = this.props.authorization_url.substring(0, this.props.authorization_url.indexOf('/', 8));
if (event.origin != authorization_domain) {
this.props.uiActions.createNotification({
content: i18n('authentication.failed', { origin: event.origin }),
level: 'error',
});
2019-09-05 15:36:11 +12:00
return false;
}
// Spotify bounced with an error
if (data.error !== undefined) {
2020-02-13 16:59:35 +13:00
this.props.uiActions.createNotification({ content: data.error, level: 'error' });
2019-09-05 15:36:11 +12:00
// No errors? We're in!
} else {
this.props.spotifyActions.authorizationGranted(data);
this.props.spotifyActions.getMe();
}
// Turn off our authorizing switch
this.setState({ authorizing: false });
}
startAuthorization() {
2019-09-05 15:36:11 +12:00
const self = this;
this.setState({ authorizing: true });
// Open an authentication request window (to spotify)
const url = `${this.props.authorization_url}?action=authorize`;
const scopes = [
'playlist-modify-private',
'playlist-modify-public',
'playlist-read-private',
'playlist-modify-private',
'user-library-read',
'user-library-modify',
'user-follow-modify',
'user-follow-read',
'user-read-email',
'user-top-read',
'user-read-currently-playing',
'user-read-playback-state',
'playlist-read-collaborative',
'ugc-image-upload', // playlist image uploading
];
const popup = window.open(`${url}&scope=${scopes.join('%20')}`, 'popup', 'height=580,width=350');
// Start timer to check our popup's state
const timer = setInterval(checkPopup, 1000);
function checkPopup() {
2017-06-12 09:14:09 +12:00
// Popup has been closed
2019-09-05 15:36:11 +12:00
if (typeof (popup) !== 'undefined' && popup) {
if (popup.closed) {
self.setState({ authorizing: false });
clearInterval(timer);
2017-06-12 09:14:09 +12:00
}
2019-09-05 15:36:11 +12:00
// Popup does not exist, so must have been blocked
} else {
self.props.uiActions.createNotification({
content: i18n('authentication.popup_blocked'),
level: 'error',
});
2019-09-05 15:36:11 +12:00
self.setState({ authorizing: false });
clearInterval(timer);
}
}
}
render() {
const { authorizing } = this.state;
const { authorized } = this.props;
if (authorized) {
2019-09-05 15:36:11 +12:00
return (
<Button
type="destructive"
working={authorizing}
onClick={() => this.props.spotifyActions.revokeAuthorization()}
tracking={{ category: 'Spotify', action: 'Logout' }}
>
<I18n path="authentication.log_out" />
</Button>
2019-09-05 15:36:11 +12:00
);
}
return (
<Button
type="primary"
working={authorizing}
onClick={() => this.startAuthorization()}
tracking={{ category: 'Spotify', action: 'Login' }}
>
<I18n path="authentication.log_in" />
</Button>
);
2019-09-05 15:36:11 +12:00
}
}
2019-09-05 15:36:11 +12:00
const mapStateToProps = (state, ownProps) => ({
authorization_url: state.spotify.authorization_url,
authorized: state.spotify.authorization,
authorizing: state.spotify.authorizing,
});
2019-09-05 15:36:11 +12:00
const mapDispatchToProps = (dispatch) => ({
uiActions: bindActionCreators(uiActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(SpotifyAuthenticationFrame);