Send authorization via pusher (partial), need to fetch me on acceptance
This commit is contained in:
@ -25,11 +25,11 @@ export default class AddToPlaylistModal extends React.Component{
|
||||
return (
|
||||
<div>
|
||||
<h4>Add to playlist</h4>
|
||||
<div className="playlists">
|
||||
<div className="list playlists">
|
||||
{
|
||||
playlists.map( playlist => {
|
||||
return (
|
||||
<div className="playlist" key={playlist.uri} onClick={ () => this.playlistSelected(playlist.uri) }>
|
||||
<div className="list-item playlist" key={playlist.uri} onClick={ () => this.playlistSelected(playlist.uri) }>
|
||||
<FontAwesome className="source" name={helpers.sourceIcon(playlist.uri)} />
|
||||
|
||||
<span className="name">{ playlist.name }</span>
|
||||
|
||||
@ -8,10 +8,12 @@ import Icon from '../Icon'
|
||||
import AddToPlaylistModal from './AddToPlaylistModal'
|
||||
import CreatePlaylistModal from './CreatePlaylistModal'
|
||||
import EditPlaylistModal from './EditPlaylistModal'
|
||||
import SendAuthorizationModal from './SendAuthorizationModal'
|
||||
|
||||
import * as uiActions from '../../services/ui/actions'
|
||||
import * as mopidyActions from '../../services/mopidy/actions'
|
||||
import * as spotifyActions from '../../services/spotify/actions'
|
||||
import * as pusherActions from '../../services/pusher/actions'
|
||||
|
||||
class Modal extends React.Component{
|
||||
|
||||
@ -32,6 +34,7 @@ class Modal extends React.Component{
|
||||
{ this.props.modal.name == 'add_to_playlist' ? <AddToPlaylistModal uiActions={this.props.uiActions} playlists={this.props.playlists} tracks_uris={this.props.modal.data.tracks_uris} /> : null }
|
||||
{ this.props.modal.name == 'create_playlist' ? <CreatePlaylistModal uiActions={this.props.uiActions} /> : null }
|
||||
{ this.props.modal.name == 'edit_playlist' ? <EditPlaylistModal uiActions={this.props.uiActions} data={this.props.modal.data} /> : null }
|
||||
{ this.props.modal.name == 'send_authorization' ? <SendAuthorizationModal uiActions={this.props.uiActions} pusherActions={this.props.pusherActions} data={this.props.modal.data} /> : null }
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -52,6 +55,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
pusherActions: bindActionCreators(pusherActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch)
|
||||
}
|
||||
|
||||
65
src/js/components/Modal/SendAuthorizationModal.js
Executable file
65
src/js/components/Modal/SendAuthorizationModal.js
Executable file
@ -0,0 +1,65 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router'
|
||||
import { createStore, bindActionCreators } from 'redux'
|
||||
|
||||
import * as uiActions from '../../services/ui/actions'
|
||||
import * as helpers from '../../helpers'
|
||||
|
||||
import Icon from '../Icon'
|
||||
|
||||
class SendAuthorizationModal extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
}
|
||||
|
||||
handleClick(e, connectionid){
|
||||
e.preventDefault()
|
||||
var data = {
|
||||
recipients: [connectionid],
|
||||
action: 'send_authorization',
|
||||
data: this.props.authorization
|
||||
}
|
||||
this.props.pusherActions.instruct( 'broadcast', data )
|
||||
this.props.uiActions.closeModal()
|
||||
return false;
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
<h4>Share Spotify authentication</h4>
|
||||
<div className="list pusher-connection-list">
|
||||
{
|
||||
this.props.connections.map( (connection, index) => {
|
||||
return (
|
||||
<div className='list-item connection' key={connection.connectionid} onClick={ e => this.handleClick(e, connection.connectionid) }>
|
||||
{ connection.username }
|
||||
|
||||
<span className="grey-text">({ connection.ip })</span>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
authorization: state.spotify.authorization,
|
||||
connections: state.pusher.connections
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
uiActions: bindActionCreators(uiActions, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SendAuthorizationModal)
|
||||
@ -99,12 +99,12 @@ class SpotifyAuthenticationFrame extends React.Component{
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
<span>
|
||||
{ this.renderAuthorizeButton() }
|
||||
|
||||
{ this.renderRefreshButton() }
|
||||
<iframe src={this.state.frameUrl} style={{ display: 'none' }}></iframe>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,21 +13,21 @@ export default class Thumbnail extends React.Component{
|
||||
shouldComponentUpdate(nextProps, nextState){
|
||||
|
||||
// no images at all, and we already know it
|
||||
if( !this.props.image &&
|
||||
!this.props.images &&
|
||||
!nextProps.image &&
|
||||
!nextProps.images ){
|
||||
return false
|
||||
}
|
||||
if(
|
||||
typeof(nextProps.image) == 'undefined' &&
|
||||
typeof(this.props.image) == 'undefined' &&
|
||||
typeof(nextProps.images) == 'undefined' &&
|
||||
typeof(this.props.images) == 'undefined'
|
||||
) return false
|
||||
|
||||
// image changed
|
||||
if( this.props.image && !nextProps.image ) return true
|
||||
if( !this.props.image && nextProps.image ) return true
|
||||
if( this.props.image && nextProps.image ) return true
|
||||
if( this.props.image != nextProps.image ) return true
|
||||
|
||||
// images array changed
|
||||
if( this.props.images && !nextProps.images ) return true
|
||||
if( !this.props.images && nextProps.images ) return true
|
||||
if( typeof(this.props.images) === 'undefined' && nextProps.images ) return true
|
||||
if( this.props.images && typeof(nextProps.images) === 'undefined' ) return true
|
||||
if( this.props.images.length != nextProps.images.length ) return true
|
||||
|
||||
// image item changed
|
||||
|
||||
@ -12,7 +12,7 @@ const localstorageMiddleware = (function(){
|
||||
|
||||
// append our state to a global variable. This gives us access to debug the store at any point
|
||||
window._store = store
|
||||
//console.log(action)
|
||||
console.log(action)
|
||||
|
||||
switch( action.type ){
|
||||
|
||||
@ -70,6 +70,7 @@ const localstorageMiddleware = (function(){
|
||||
Object.assign(
|
||||
spotify,{
|
||||
authorized: true,
|
||||
authorization: action.data,
|
||||
access_token: action.data.access_token,
|
||||
refresh_token: action.data.refresh_token,
|
||||
token_expiry: action.data.token_expiry
|
||||
|
||||
@ -43,10 +43,10 @@ export function getConnectionList(){
|
||||
}
|
||||
}
|
||||
|
||||
export function instruct( action, data = null ){
|
||||
export function instruct( message_type, data = null ){
|
||||
return {
|
||||
type: 'PUSHER_INSTRUCT',
|
||||
action: action,
|
||||
message_type: message_type,
|
||||
data: data
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ const PusherMiddleware = (function(){
|
||||
|
||||
// handle all manner of socket messages
|
||||
const handleMessage = (ws, store, message) => {
|
||||
console.log(message)
|
||||
switch( message.action ){
|
||||
default:
|
||||
var name = 'unspecified'
|
||||
@ -87,7 +88,7 @@ const PusherMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'PUSHER_INSTRUCT':
|
||||
switch( action.action ){
|
||||
switch( action.message_type ){
|
||||
case 'query':
|
||||
makeRequest( action.data )
|
||||
break
|
||||
@ -150,6 +151,15 @@ const PusherMiddleware = (function(){
|
||||
var notification = new notification( title, options );
|
||||
break;
|
||||
|
||||
case 'PUSHER_SEND_AUTHORIZATION':
|
||||
if( window.confirm('Spotify authorization received. Do you want to import?') ){
|
||||
store.dispatch({ type: 'SPOTIFY_AUTHORIZATION_GRANTED', data: action.data })
|
||||
window.location.reload(true)
|
||||
}else{
|
||||
console.log('Authorization ignored')
|
||||
}
|
||||
break
|
||||
|
||||
// This action is irrelevant to us, pass it on to the next middleware
|
||||
default:
|
||||
return next(action);
|
||||
|
||||
@ -13,6 +13,7 @@ import VersionManager from '../components/VersionManager'
|
||||
import Header from '../components/Header'
|
||||
import Thumbnail from '../components/Thumbnail'
|
||||
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
import * as pusherActions from '../services/pusher/actions'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
@ -108,6 +109,18 @@ class Settings extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
renderSendAuthorizationButton(){
|
||||
if( !this.props.spotify.authorized ) return null
|
||||
|
||||
return (
|
||||
<button onClick={e => this.props.uiActions.openModal('send_authorization', {}) }>
|
||||
<FontAwesome name="share-square-o" />
|
||||
|
||||
Share authentication
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="view settings-view">
|
||||
@ -214,6 +227,8 @@ class Settings extends React.Component{
|
||||
<div className="name">Authentication</div>
|
||||
<div className="input">
|
||||
<SpotifyAuthenticationFrame />
|
||||
|
||||
{ this.renderSendAuthorizationButton() }
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -278,6 +293,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
pusherActions: bindActionCreators(pusherActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch)
|
||||
|
||||
@ -8,6 +8,7 @@ import Thumbnail from '../components/Thumbnail'
|
||||
import PlaylistGrid from '../components/PlaylistGrid'
|
||||
import FollowButton from '../components/FollowButton'
|
||||
import LazyLoadListener from '../components/LazyLoadListener'
|
||||
import Header from '../components/Header'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
@ -51,6 +52,9 @@ class User extends React.Component{
|
||||
|
||||
return (
|
||||
<div className="view user-view">
|
||||
|
||||
<Header icon="play" title="User" />
|
||||
|
||||
<div className="intro">
|
||||
<Thumbnail circle={true} size="medium" images={ this.props.user.images } />
|
||||
|
||||
|
||||
@ -66,18 +66,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
.playlists {
|
||||
.list {
|
||||
@include clearfix();
|
||||
|
||||
.playlist {
|
||||
.list-item {
|
||||
float: left;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 49%;
|
||||
padding: 16px 20px 16px 30px;
|
||||
padding: 16px 18px;
|
||||
border-bottom: 1px solid $mid_grey;
|
||||
position: relative;
|
||||
|
||||
&.playlist {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.source {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
@ -108,8 +112,8 @@
|
||||
padding: 50px;
|
||||
width: 80%;
|
||||
|
||||
.playlists {
|
||||
.playlist {
|
||||
.list {
|
||||
.list-item {
|
||||
float: none !important;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user