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
@@ -75,11 +93,22 @@ class Settings extends React.Component{
Pusher
@@ -87,18 +116,22 @@ class Settings extends React.Component{
Spotify
@@ -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%;
+ }
}
}