From 696e385b7e152e08f49aa4e5ee215fc8b2019a8b Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Fri, 28 Oct 2016 09:14:29 +1300 Subject: [PATCH] Pusher username management; Spotify vs mopidy middleware glitching --- src/js/bootstrap.js | 7 ++- src/js/components/PusherConnectionList.js | 61 +++++++++++++++++++ src/js/services/localstorage/middleware.js | 21 ++++++- src/js/services/pusher/actions.js | 21 ++++++- src/js/services/pusher/middleware.js | 20 +++++-- src/js/services/pusher/reducer.js | 15 +++-- src/js/services/spotify/middleware.js | 3 +- src/js/views/Settings.js | 70 +++++++++++++++++----- src/scss/global/_core.scss | 4 ++ src/scss/global/_forms.scss | 9 ++- 10 files changed, 199 insertions(+), 32 deletions(-) create mode 100755 src/js/components/PusherConnectionList.js diff --git a/src/js/bootstrap.js b/src/js/bootstrap.js index 011d618f..f4d79ddd 100755 --- a/src/js/bootstrap.js +++ b/src/js/bootstrap.js @@ -22,17 +22,22 @@ let reducers = combineReducers({ }); // set application defaults +// TODO: Look at using propTypes in the component for these falsy initial states var initialState = { mopidy: { + connected: false, host: window.location.hostname, port: 6680, volume: 0, progress: 0 }, pusher: { + connections: [], + connected: false, port: 6681 }, spotify: { + connected: false, country: 'NZ', locale: 'en_NZ', me: false @@ -65,7 +70,7 @@ if( localStorage.getItem('spotify') ){ let store = createStore( reducers, initialState, - applyMiddleware( thunk, localstorageMiddleware, pusherMiddleware, mopidyMiddleware, spotifyMiddleware ) + applyMiddleware( thunk, localstorageMiddleware, mopidyMiddleware, pusherMiddleware, spotifyMiddleware ) ); export default store; diff --git a/src/js/components/PusherConnectionList.js b/src/js/components/PusherConnectionList.js new file mode 100755 index 00000000..9da9bcfe --- /dev/null +++ b/src/js/components/PusherConnectionList.js @@ -0,0 +1,61 @@ + +import React, { PropTypes } from 'react' +import { connect } from 'react-redux' +import { Link } from 'react-router' +import { createStore, bindActionCreators } from 'redux' + +import FontAwesome from 'react-fontawesome' + +import * as pusherActions from '../services/pusher/actions' + +class PusherConnectionList extends React.Component{ + + constructor(props) { + super(props); + } + + componentDidMount(){ + if( this.props.pusher.connected ){ + this.props.pusherActions.getConnectionList(); + } + } + + componentWillReceiveProps(newProps){ + if( !this.props.pusher.connected && newProps.pusher.connected ){ + this.props.pusherActions.getConnectionList(); + } + } + + render(){ + if( !this.props.pusher.connected ) return null; + if( typeof(this.props.pusher.connections) == 'undefined' || this.props.pusher.connections.length <= 0 ) return null; + + return ( +
+ { + this.props.pusher.connections.map( (connection, index) => { + return ( +
+
{ connection.username }
+
{ connection.ip }
+
{ connection.connectionid }
+
+ ); + }) + } +
+ ); + } +} + +const mapStateToProps = (state, ownProps) => { + return state; +} + +const mapDispatchToProps = (dispatch) => { + return { + pusherActions: bindActionCreators(pusherActions, dispatch) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(PusherConnectionList) \ No newline at end of file diff --git a/src/js/services/localstorage/middleware.js b/src/js/services/localstorage/middleware.js index 074b25d9..59e7281e 100755 --- a/src/js/services/localstorage/middleware.js +++ b/src/js/services/localstorage/middleware.js @@ -6,7 +6,7 @@ const localstorageMiddleware = (function(){ **/ return store => next => action => { - console.log(action) + console.log(action, store.getState()) // proceed as normal first // this way, any reducers and middleware do their thing BEFORE we store our new state @@ -14,6 +14,25 @@ const localstorageMiddleware = (function(){ switch( action.type ){ + case 'PUSHER_SET_CONFIG': + var pusher = { + username: action.config.username, + port: action.config.port + }; + localStorage.setItem('pusher', JSON.stringify(pusher)); + break; + + case 'PUSHER_CONNECTED': + var pusher = JSON.parse( localStorage.getItem('pusher') ); + if( !pusher ) pusher = {}; + Object.assign( + pusher,{ + connectionid: action.connection.connectionid + } + ); + localStorage.setItem('pusher', JSON.stringify(pusher)); + break; + case 'MOPIDY_SET_CONFIG': var mopidy = { host: action.config.host, diff --git a/src/js/services/pusher/actions.js b/src/js/services/pusher/actions.js index 760659db..2682365d 100755 --- a/src/js/services/pusher/actions.js +++ b/src/js/services/pusher/actions.js @@ -10,6 +10,14 @@ export function setConfig( config ){ } } +export function setUsername( username ){ + return { + type: 'PUSHER_INSTRUCT', + action: 'set_username', + data: { username: username } + } +} + export function connect(){ return { type: 'PUSHER_CONNECT' @@ -22,10 +30,17 @@ export function disconnect(){ } } -export function instruct( call, value ){ +export function getConnectionList(){ return { type: 'PUSHER_INSTRUCT', - call: call, - value: value + action: 'get_connections' + } +} + +export function instruct( action, data = null ){ + return { + type: 'PUSHER_INSTRUCT', + action: action, + data: data } } \ No newline at end of file diff --git a/src/js/services/pusher/middleware.js b/src/js/services/pusher/middleware.js index 4b117815..c22cb33e 100755 --- a/src/js/services/pusher/middleware.js +++ b/src/js/services/pusher/middleware.js @@ -40,16 +40,23 @@ const PusherMiddleware = (function(){ store.dispatch({ type: 'PUSHER_CONNECTING' }); var state = store.getState(); + var connection = { + clientid: Math.random().toString(36).substr(2, 9), + connectionid: helpers.generateGuid(), + username: Math.random().toString(36).substr(2, 9) + } + //if( state.pusher.username ) connection.username = state.pusher.username; socket = new WebSocket( - 'ws://'+state.mopidy.host+':'+state.pusher.port+'/pusher' + 'ws://'+state.mopidy.host+':'+state.pusher.port+'/pusher', + [ connection.clientid, connection.connectionid, connection.username ] ); - socket.onopen = function(){ - store.dispatch({ type: 'PUSHER_CONNECTED' }); + socket.onopen = () => { + store.dispatch({ type: 'PUSHER_CONNECTED', connection: connection }); }; - socket.onmessage = function(message){ + socket.onmessage = (message) => { var message = JSON.parse(message.data); handleMessage( socket, store, message ) }; @@ -58,6 +65,11 @@ const PusherMiddleware = (function(){ case 'PUSHER_CONNECTED': makeRequest({ action: 'get_version' }); + return next(action); + break; + + case 'PUSHER_INSTRUCT': + makeRequest({ action: action.action, data: action.data }); break; // This action is irrelevant to us, pass it on to the next middleware diff --git a/src/js/services/pusher/reducer.js b/src/js/services/pusher/reducer.js index 01cacbcb..9f2f8628 100755 --- a/src/js/services/pusher/reducer.js +++ b/src/js/services/pusher/reducer.js @@ -3,19 +3,22 @@ export default function reducer(pusher = {}, action){ switch (action.type) { case 'PUSHER_CONNECTED': - return Object.assign({}, pusher, { connected: true, connecting: false }); + return Object.assign({}, pusher, { connected: true, connecting: false, connectionid: action.connection.connectionid }); case 'PUSHER_DISCONNECTED': return Object.assign({}, pusher, { connected: false, connecting: false }); - case 'PUSHER_SET_PORT': - return Object.assign({}, pusher, { port: action.port }); + case 'PUSHER_SET_CONFIG': + return Object.assign({}, pusher, { + username: action.username, + port: action.port + }); case 'PUSHER_CLIENT_CONNECTED': - return Object.assign({}, pusher, { connections: action.data }); + return Object.assign({}, pusher, { connection: action.data }); - case 'PUSHER_CONNECTIONS_LOADED': - return Object.assign({}, pusher, { connections: action.data }); + case 'PUSHER_CONNECTIONS': + return Object.assign({}, pusher, { connections: action.data.connections }); case 'PUSHER_VERSION': return Object.assign({}, pusher, { version: action.data }); diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js index c21853f6..b7420df4 100755 --- a/src/js/services/spotify/middleware.js +++ b/src/js/services/spotify/middleware.js @@ -12,7 +12,8 @@ const SpotifyMiddleware = (function(){ switch(action.type){ // when our mopidy server current track changes - case 'MOPIDY_CURRENTTLTRACK': + case 'MOPIDY_CURRENTTLTRACK_XX': + // DISABLED AS IT CAUSES ISSUE // proceed as usual so we don't inhibit default functionality next(action) diff --git a/src/js/views/Settings.js b/src/js/views/Settings.js index 7a9b5585..826f9a22 100755 --- a/src/js/views/Settings.js +++ b/src/js/views/Settings.js @@ -6,8 +6,10 @@ import { bindActionCreators } from 'redux' import FontAwesome from 'react-fontawesome' import SpotifyAuthenticationFrame from '../components/SpotifyAuthenticationFrame' import ConfirmationButton from '../components/ConfirmationButton' +import PusherConnectionList from '../components/PusherConnectionList' import Header from '../components/Header' +import * as pusherActions from '../services/pusher/actions' import * as mopidyActions from '../services/mopidy/actions' import * as spotifyActions from '../services/spotify/actions' @@ -15,16 +17,27 @@ class Settings extends React.Component{ constructor(props) { super(props); - this.state = { mopidy_host: this.props.mopidy.host, mopidy_port: this.props.mopidy.port, + pusher_username: '', pusher_port: this.props.pusher.port, spotify_country: this.props.spotify.country, spotify_locale: this.props.spotify.locale }; } + componentWillReceiveProps( newProps ){ + if( this.props.pusher.connectionid != newProps.pusher.connectionid ){ + + function isCurrentConnection(connection){ + return connection.connectionid == newProps.pusher.connectionid; + } + var currentConnection = newProps.pusher.connections.find(isCurrentConnection); + this.setState({ pusher_username: currentConnection.username }) + } + } + resetAllSettings(){ localStorage.clear(); window.location.reload(true); @@ -35,12 +48,13 @@ class Settings extends React.Component{ window.location.reload(true); } - setSpotifyConfig(){ - this.props.spotifyActions.setConfig({ country: this.state.spotify_country, locale: this.state.spotify_locale }); - } - setPusherConfig(){ this.props.pusherActions.setConfig({ port: this.state.pusher_port }); + this.props.pusherActions.setUsername( this.state.pusher_username ); + } + + setSpotifyConfig(){ + this.props.spotifyActions.setConfig({ country: this.state.spotify_country, locale: this.state.spotify_locale }); } render(){ @@ -56,18 +70,22 @@ class Settings extends React.Component{

Mopidy

this.setMopidyConfig()}>
@@ -75,11 +93,22 @@ class Settings extends React.Component{

Pusher

this.setPusherConfig()}> +
@@ -87,18 +116,22 @@ class Settings extends React.Component{

Spotify

this.setSpotifyConfig()}>
@@ -107,6 +140,14 @@ class Settings extends React.Component{ this.resetAllSettings()} /> +

Advanced

+ + ); @@ -126,6 +167,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = (dispatch) => { return { + pusherActions: bindActionCreators(pusherActions, dispatch), mopidyActions: bindActionCreators(mopidyActions, dispatch), spotifyActions: bindActionCreators(spotifyActions, dispatch) } diff --git a/src/scss/global/_core.scss b/src/scss/global/_core.scss index 51356df5..c0b39092 100755 --- a/src/scss/global/_core.scss +++ b/src/scss/global/_core.scss @@ -91,4 +91,8 @@ main { .cf{ @include clearfix; +} + +.one-liner{ + @include one_line_text; } \ No newline at end of file diff --git a/src/scss/global/_forms.scss b/src/scss/global/_forms.scss index b3a2aadb..b4af7f0f 100755 --- a/src/scss/global/_forms.scss +++ b/src/scss/global/_forms.scss @@ -87,8 +87,13 @@ label { float: left; } - input { - width: 60%; + .input { + width: 85%; + float: left; + + input { + width: 60%; + } } }