浏览代码

Got more work done on the station pages. Converted previous things mostly to use Redux and added more functionality to volume slider and added more event listeners.

KrisVos130 7 年之前
父节点
当前提交
a019484030

+ 3 - 1
backend/logic/actions/stations.js

@@ -134,7 +134,9 @@ cache.sub('privatePlaylist.selected', data => {
 });
 
 cache.sub('station.pause', stationId => {
-	utils.emitToRoom(`station.${stationId}`, "event:stations.pause");
+	stations.getStation(stationId, (err, station) => {
+		utils.emitToRoom(`station.${stationId}`, "event:stations.pause", station.pausedAt);
+	});
 });
 
 cache.sub('station.resume', stationId => {

+ 23 - 0
frontend/app/js/actions/songPlayer.js

@@ -0,0 +1,23 @@
+export const CHANGE_SONG = "CHANGE_SONG";
+export const SET_TIME_ELAPSED = "SET_TIME_ELAPSED";
+export const UPDATE_TIME_PAUSED = "UPDATE_TIME_PAUSED";
+
+export function changeSong(song) {
+	return {
+		type: CHANGE_SONG,
+		song,
+	};
+}
+export function setTimeElapsed(paused, pausedAt) {
+	return {
+		type: SET_TIME_ELAPSED,
+		paused,
+		pausedAt,
+	};
+}
+export function updateTimePaused(timePaused) {
+	return {
+		type: UPDATE_TIME_PAUSED,
+		timePaused,
+	};
+}

+ 27 - 0
frontend/app/js/actions/station.js

@@ -0,0 +1,27 @@
+export const INITIALIZE_STATION = "INITIALIZE_STATION";
+export const PAUSE_STATION = "PAUSE_STATION";
+export const RESUME_STATION = "RESUME_STATION";
+export const LEAVE_STATION = "LEAVE_STATION";
+
+export function initializeStation(station) {
+	return {
+		type: INITIALIZE_STATION,
+		station,
+	};
+}
+export function pauseStation(pausedAt) {
+	return {
+		type: PAUSE_STATION,
+		pausedAt,
+	};
+}
+export function resumeStation() {
+	return {
+		type: RESUME_STATION,
+	};
+}
+export function leaveStation() {
+	return {
+		type: LEAVE_STATION,
+	};
+}

+ 0 - 1
frontend/app/js/app.jsx

@@ -50,7 +50,6 @@ class App extends Component { // eslint-disable-line react/no-multi-comp
 
 		let volume = parseFloat(localStorage.getItem("volume"));
 		volume = (typeof volume === "number" && !isNaN(volume)) ? volume : 20;
-		console.log("VOLUME", volume);
 		localStorage.setItem("volume", volume);
 		dispatch(initializeVolume(volume));
 	}

+ 31 - 12
frontend/app/js/components/AuthRoute.jsx

@@ -3,6 +3,7 @@ import { connect } from "react-redux";
 import PropTypes from "prop-types";
 import { Redirect, Route } from "react-router-dom";
 import { translate } from "react-i18next";
+import { initializeStation } from "actions/station";
 
 import io from "io";
 
@@ -30,6 +31,10 @@ function clone(obj) {
 	loggedIn: state.user.get("loggedIn"),
 	role: state.user.get("role"),
 	authProcessed: state.user.get("authProcessed"),
+	station: {
+		stationId: state.station.get("id"),
+		name: state.station.get("name"),
+	},
 }))
 
 @translate(["general"], { wait: true })
@@ -88,30 +93,44 @@ export default class AuthRoute extends Component {
 	getStationData = () => {
 		io.getSocket(socket => {
 			socket.emit("stations.findByName", this.state.stationName, res => {
-				this.setState({
-					receivedStationData: true,
-					stationData: res.data,
-				});
+				if (res.status === "success") {
+					this.props.dispatch(initializeStation({
+						//TODO Refactor this to be better optimized
+						stationId: res.data._id,
+						name: res.data.name,
+						displayName: res.data.displayName,
+						description: res.data.description,
+						privacy: res.data.privacy,
+						locked: res.data.locked,
+						partyMode: res.data.partyMode,
+						owner: res.data.owner,
+						privatePlaylist: res.data.privatePlaylist,
+						type: res.data.type,
+						paused: res.data.paused,
+						pausedAt: res.data.pausedAt,
+					}));
+				} else {
+					this.setState({
+						noStation: true,
+					});
+				}
 			});
 		});
 	};
 
 	render() {
 		const { auth, role, loggedIn, authProcessed, t } = this.props;
-		const { stationName, waitingFor, receivedStationData, stationData } = this.state;
+		const { waitingFor, receivedStationData } = this.state;
 
 		if (this.state.continue) {
 			return <PropsRoute props={ this.props } component={ this.props.component }/>
-		} else if (waitingFor === "station" && receivedStationData) {
-			if (stationData) {
-				const props = clone(this.props);
+		} else if (waitingFor === "station") {
+			if (this.props.station.stationId) {
 				// TODO Replace the above hack with a proper Object.clone
-				props.stationName = stationName;
-				props.stationData = stationData;
-				window.props = props; //TODO Replace
 				return <Route component={ this.props.component } />;
+			} else if (this.state.noStation) {
+				return <Redirect to={ "/" } />;
 			}
-			return <Redirect to={ "/" } />;
 		} else if (waitingFor === "auth" && authProcessed) {
 			if (auth === "required") {
 				if (loggedIn) return <Route props={ this.props } component={ this.props.component } />;

+ 4 - 0
frontend/app/js/reducers/index.js

@@ -1,8 +1,12 @@
 import { combineReducers } from "redux";
 import user from "reducers/user";
 import volume from "reducers/volume";
+import songPlayer from "reducers/songPlayer";
+import station from "reducers/station";
 
 export default combineReducers({
 	user,
 	volume,
+	songPlayer,
+	station,
 });

+ 64 - 0
frontend/app/js/reducers/songPlayer.js

@@ -0,0 +1,64 @@
+import { Map } from "immutable";
+
+import {
+	CHANGE_SONG,
+	SET_TIME_ELAPSED,
+	UPDATE_TIME_PAUSED,
+} from "actions/songPlayer";
+
+const initialState = Map({
+	simple: true,
+	exists: false,
+	title: "",
+	artists: [],
+	duration: 0,
+	skipDuration: 0,
+	songId: "",
+	dislikes: 0,
+	likes: 0,
+	startedAt: 0,
+	timePaused: 0,
+	timeElapsed: 0,
+});
+
+const actionsMap = {
+	[CHANGE_SONG]: (state, action) => {
+		let obj = {};
+		let exists = !!action.song;
+		obj.simple = (exists) ? (action.song.likes === -1 && action.song.dislikes === -1) : true;
+		obj.exists = exists;
+		if (exists) {
+			obj.title = action.song.title;
+			obj.artists = action.song.artists;
+			obj.duration = action.song.duration;
+			obj.skipDuration = action.song.skipDuration;
+			obj.songId = action.song.songId;
+			obj.dislikes = action.song.dislikes;
+			obj.likes = action.song.likes;
+			obj.startedAt = action.song.startedAt;
+			obj.timePaused = action.song.timePaused;
+			obj.timeElapsed = 0;
+		} else {
+			obj = initialState;
+		}
+
+		return state.merge(obj);
+	},
+	[SET_TIME_ELAPSED]: (state, action) => {
+		let timePausedNow = 0;
+		if (action.paused) timePausedNow = Date.now() - action.pausedAt;
+		return state.merge({
+			timeElapsed: (Date.now() - state.get("startedAt") - state.get("timePaused") - timePausedNow) / 1000,
+		});
+	},
+	[UPDATE_TIME_PAUSED]: (state, action) => {
+		return state.merge({
+			timePaused: action.timePaused,
+		});
+	},
+};
+
+export default function reducer(state = initialState, action = {}) {
+	const fn = actionsMap[action.type];
+	return fn ? fn(state, action) : state;
+}

+ 59 - 0
frontend/app/js/reducers/station.js

@@ -0,0 +1,59 @@
+import { Map } from "immutable";
+
+import {
+	INITIALIZE_STATION,
+	PAUSE_STATION,
+	RESUME_STATION,
+	LEAVE_STATION,
+} from "actions/station";
+
+const initialState = Map({
+	id: "",
+	name: "",
+	displayName: "",
+	description: "",
+	paused: true,
+	pausedAt: 0,
+	privacy: "public",
+	type: "official",
+	locked: false,
+	partyMode: false,
+	privatePlaylist: "",
+});
+
+const actionsMap = {
+	[INITIALIZE_STATION]: (state, action) => {
+		return state.merge({
+			id: action.station.stationId,
+			name: action.station.name,
+			displayName: action.station.displayName,
+			description: action.station.description,
+			paused: action.station.paused,
+			pausedAt: action.station.pausedAt,
+			privacy: action.station.privacy,
+			type: action.station.type,
+			locked: action.station.locked,
+			partyMode: action.station.partyMode,
+			privatePlaylist: action.station.privatePlaylist,
+		});
+	},
+	[PAUSE_STATION]: (state, action) => {
+		return state.merge({
+			paused: true,
+			pausedAt: action.pausedAt,
+		});
+	},
+	[RESUME_STATION]: (state, action) => {
+		return state.merge({
+			paused: false,
+		});
+	},
+	[LEAVE_STATION]: (state, action) => {
+		return initialState;
+	},
+};
+
+export default function reducer(state = initialState, action = {}) {
+	const fn = actionsMap[action.type];
+	return fn ? fn(state, action) : state;
+}

+ 54 - 37
frontend/app/js/views/Station/Player.jsx

@@ -4,11 +4,21 @@ const i18next = require("i18next");
 
 import { connect } from "react-redux";
 
+import { pauseStation, unpauseStation } from "actions/station";
+
 const t = i18next.t;
 let getPlayerCallbacks = [];
 
 @connect(state => ({
 	volume: state.volume.get("volume"),
+	muted: state.volume.get("muted"),
+	songId: state.songPlayer.get("songId"),
+	startedAt: state.songPlayer.get("startedAt"),
+	timePaused: state.songPlayer.get("timePaused"),
+	skipDuration: state.songPlayer.get("skipDuration"),
+	pausedAt: state.songPlayer.get("pausedAt"),
+	exists: state.songPlayer.get("exists"),
+	paused: state.station.get("paused"),
 }))
 export default class Player extends Component {
 	static propTypes = {
@@ -27,10 +37,10 @@ export default class Player extends Component {
 				initializing: false,
 				ready: false,
 				loading: false,
-				paused: true,
-				pausedAt: null, // Find better spot for this one
 			},
 		};
+
+		if (props.paused) this.pause();
 	}
 
 	componentDidMount() {
@@ -50,70 +60,58 @@ export default class Player extends Component {
 		});
 	}
 
-	playSong(songId, skipDuration, timePaused, startedAt, cb) {
+	playSong() {
 		this.getPlayer((player) => {
-			let pausedAt = (this.state.player.paused) ? Date.now() : null;
 			this.setState({
-				song: {
-					songId,
-					skipDuration,
-					timePaused,
-					startedAt,
-				},
 				player: {
 					...this.state.player,
-					pausedAt,
 					loading: true,
 				},
 			});
 
-			player.loadVideoById(songId, this.getProperVideoTime());
-			cb();
+			player.loadVideoById(this.props.songId, this.getProperVideoTime());
 		});
 	}
 
 	getProperVideoTime = () => {
-		if (this.state.song) {
-			return this.getTimeElapsed() / 1000 + this.state.song.skipDuration;
+		if (this.props.exists) {
+			return this.getTimeElapsed() / 1000 + this.props.skipDuration;
 		} else return 0;
 	};
 
 	getTimeElapsed = () => {
-		if (this.state.song) {
+		if (this.props.exists) {
 			// TODO Replace with Date.currently
 			let timePausedNow = 0;
-			if (this.state.player.paused) timePausedNow = Date.now() - this.state.player.pausedAt;
-			return Date.now() - this.state.song.startedAt - this.state.song.timePaused - timePausedNow;
+			if (this.props.paused) timePausedNow = Date.now() - this.props.pausedAt;
+			return Date.now() - this.props.startedAt - this.props.timePaused - timePausedNow;
 		} else return 0;
 	};
 
 	pause() {
 		this.getPlayer((player) => {
-			if (this.state.player.paused) return;
-			this.setState({
-				player: {
-					...this.state.player,
-					paused: true,
-					pausedAt: Date.now(),
-				},
-			});
 			player.pauseVideo();
 		});
 	}
 
 	resume() {
 		this.getPlayer((player) => {
-			if (!this.state.player.paused) return;
-			this.setState({
-				player: {
-					...this.state.player,
-					paused: false,
-				},
-			});
 			player.playVideo();
 		});
 	}
 
+	mute() {
+		this.getPlayer((player) => {
+			player.mute();
+		});
+	}
+
+	unmute() {
+		this.getPlayer((player) => {
+			player.unMute();
+		});
+	}
+
 	initializePlayer = () => {
 		// TODO Ensure YT.Player exists
 		if (this.state.player.ready || this.state.player.initializing) return;
@@ -135,7 +133,6 @@ export default class Player extends Component {
 							...this.state.player,
 							initializing: false,
 							ready: true,
-							test: 1,
 						},
 					});
 
@@ -144,6 +141,8 @@ export default class Player extends Component {
 					});
 
 					this.player.setVolume(this.props.volume);
+					if (this.props.muted) this.mute();
+					else this.unmute();
 				},
 				"onError": function(err) {
 					console.log("iframe error", err);
@@ -158,12 +157,12 @@ export default class Player extends Component {
 									loading: false,
 								},
 							});
-							if (this.state.player.paused) player.pauseVideo();
-							if (this.state.player.paused || this.state.player.loading) player.seekTo(this.getProperVideoTime(), true);
+							if (this.props.paused) player.pauseVideo();
+							if (this.props.paused || this.state.player.loading) player.seekTo(this.getProperVideoTime(), true);
 						}
 
 						if (event.data === YT.PlayerState.PAUSED) {
-							if (!this.state.player.paused) {
+							if (!this.props.paused) {
 								player.seekTo(this.getProperVideoTime(), true);
 								player.playVideo();
 							}
@@ -187,6 +186,24 @@ export default class Player extends Component {
 		}
 	}
 
+	componentDidUpdate(prevProps, prevState) {
+		if (this.props.songId !== prevProps.songId && this.props.startedAt !== prevProps.startedAt) { //Add unique token instead of comparing startedAt
+			if (this.props.exists) {
+				this.playSong();
+			} else this.clearSong();
+		}
+
+		if (this.props.paused !== prevProps.paused) { //Add unique token instead of comparing startedAt
+			if (this.props.paused) this.pause();
+			else this.resume();
+		}
+
+		if (this.props.muted !== prevProps.muted) {
+			if (this.props.muted) this.mute();
+			else this.unmute();
+		}
+	}
+
 	render() {
 		return (
 			<div id="player"/>

+ 23 - 32
frontend/app/js/views/Station/Seekerbar.jsx

@@ -1,6 +1,13 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 
+import { connect } from "react-redux";
+
+@connect(state => ({
+	timeElapsed: state.songPlayer.get("timeElapsed") * 1000,
+	timeTotal: state.songPlayer.get("duration") * 1000,
+	paused: state.station.get("paused"),
+}))
 export default class Seekerbar extends Component {
 	static propTypes = {
 		onRef: PropTypes.func,
@@ -14,47 +21,31 @@ export default class Seekerbar extends Component {
 		super(props);
 
 		this.state = {
-			timeTotal: 0,
-			timeElapsed: 0,
 			timeElapsedGuess: 0,
 			percentage: 0,
 		};
 
 		setInterval(() => {
-			let timeElapsedGuess = this.state.timeElapsedGuess;
-			timeElapsedGuess += 15;
-
-			if (timeElapsedGuess <= this.state.timeElapsed) {
-				timeElapsedGuess = this.state.timeElapsed;
+			if (!this.props.paused) {
+				let timeElapsedGuess = this.state.timeElapsedGuess;
+				timeElapsedGuess += 15;
+
+				if (timeElapsedGuess <= this.props.timeElapsed) {
+					timeElapsedGuess = this.props.timeElapsed;
+				}
+
+				this.setState({
+					percentage: (timeElapsedGuess / this.props.timeTotal) * 100,
+					timeElapsedGuess,
+				});
+			} else {
+				this.setState({
+					percentage: (this.props.timeElapsed / this.props.timeTotal) * 100,
+				});
 			}
-
-			this.setState({
-				percentage: (timeElapsedGuess / this.state.timeTotal) * 100,
-				timeElapsedGuess,
-			});
 		}, 50);
 	}
 
-	componentDidMount() {
-		this.props.onRef(this);
-	}
-	componentWillUnmount() {
-		this.props.onRef(null);
-	}
-
-	setTime = (timeTotal) => {
-		this.setState({
-			timeTotal: timeTotal * 1000,
-			timeElapsed: 0,
-		});
-	};
-
-	setTimeElapsed = (time) => {
-		this.setState({
-			timeElapsed: time * 1000,
-		});
-	};
-
 	render() {
 		return (
 			<span style={{"width": this.state.percentage + "%", "background-color": "blue", "height": "100%", "display": "inline-block"}}/>

+ 0 - 48
frontend/app/js/views/Station/Time.jsx

@@ -1,48 +0,0 @@
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-
-const formatTime = (duration) => {
-	let d = moment.duration(duration, "seconds");
-	if (duration < 0) return "0:00";
-	return ((d.hours() > 0) ? (d.hours() < 10 ? ("0" + d.hours() + ":") : (d.hours() + ":")) : "") + (d.minutes() + ":") + (d.seconds() < 10 ? ("0" + d.seconds()) : d.seconds());
-};
-
-export default class Time extends Component {
-	static propTypes = {
-		onRef: PropTypes.func,
-	};
-
-	static defaultProps = {
-		onRef: () => {},
-	};
-
-	constructor(props) {
-		super(props);
-
-		this.state = {
-			time: 0,
-		};
-	}
-
-	componentDidMount() {
-		this.props.onRef(this);
-	}
-	componentWillUnmount() {
-		this.props.onRef(null);
-	}
-
-	formatTime = formatTime;
-	static formatTime = formatTime;
-
-	setTime = (time) => {
-		this.setState({
-			time,
-		});
-	};
-
-	render() {
-		return (
-			<span>{ this.formatTime(this.state.time) }</span>
-		);
-	}
-}

+ 6 - 5
frontend/app/js/views/Station/VolumeSlider.jsx

@@ -14,8 +14,9 @@ export default class VolumeSlider extends Component {
 		super(props);
 	}
 
-	changeVolumeHandler = (e) => {
-		let volume = e.target.value / 100;
+	changeVolumeHandler = (volume) => {
+		volume = volume / 100;
+		localStorage.setItem("volume", volume);
 		this.props.dispatch(changeVolume(volume));
 	};
 
@@ -33,11 +34,11 @@ export default class VolumeSlider extends Component {
 				<h2>{ this.props.volume }. Muted: { (this.props.muted) ? "true" : "false" }</h2>
 				{
 					(this.props.muted) ? ([
-						<span key="unmuteButton" onClick={ this.unmuteVolume }>UNMUTE</span>,
+						<i className="material-icons" key="unmuteButton" onClick={ this.unmuteVolume }>volume_off</i>,
 						<input key="disabledVolumeInput" type="range" min="0" max="10000" value="0" disabled/>,
 					]) : ([
-						<span key="muteButton" onClick={ this.muteVolume }>MUTE</span>,
-						<input key="volumeInput" type="range" min="0" max="10000" onChange={ this.changeVolumeHandler }/>, //Add default value
+						<i className="material-icons" key="muteButton" onClick={ this.muteVolume }>volume_up</i>,
+						<input key="volumeInput" type="range" min="0" max="10000" value={ this.props.volume * 100 } onChange={ (e) => { this.changeVolumeHandler(e.target.value) } }/>, //Add default value
 					])
 				}
 			</div>

+ 78 - 94
frontend/app/js/views/Station/index.jsx

@@ -5,28 +5,48 @@ import PropTypes from "prop-types";
 import { translate, Trans } from "react-i18next";
 
 import Player from "./Player";
-import Time from "./Time";
 import Seekerbar from "./Seekerbar";
 import VolumeSlider from "./VolumeSlider";
 
 import { changeVolume } from "actions/volume";
+import { changeSong, setTimeElapsed, timePaused } from "actions/songPlayer";
+import { pauseStation, resumeStation } from "actions/station";
 
 import { connect } from "react-redux";
 
 import io from "io";
 import config from "config";
+import {updateTimePaused} from "../../actions/songPlayer";
 
 const Aux = (props) => {
 	return props.children;
 };
 
+const formatTime = (duration) => {
+	let d = moment.duration(duration, "seconds");
+	if (duration < 0) return "0:00";
+	return ((d.hours() > 0) ? (d.hours() < 10 ? ("0" + d.hours() + ":") : (d.hours() + ":")) : "") + (d.minutes() + ":") + (d.seconds() < 10 ? ("0" + d.seconds()) : d.seconds());
+};
+
 @connect(state => ({
 	user: {
 		userId: state.user.get("userId"),
 		role: state.user.get("role"),
 	},
 	loggedIn: state.user.get("loggedIn"),
-	volume: state.volume.get("volume"),
+	songTitle: state.songPlayer.get("title"),
+	songDuration: state.songPlayer.get("duration"),
+	songTimeElapsed: state.songPlayer.get("timeElapsed"),
+	songArtists: state.songPlayer.get("artists"),
+	simpleSong: state.songPlayer.get("simple"),
+	songExists: state.songPlayer.get("exists"),
+	station: {
+		stationId: state.station.get("id"),
+		name: state.station.get("name"),
+		displayName: state.station.get("displayName"),
+		paused: state.station.get("paused"),
+		pausedAt: state.station.get("pausedAt"),
+	},
 }))
 
 @translate(["station"], { wait: true })
@@ -39,88 +59,46 @@ export default class Station extends Component {
 		t: () => {},
 	};
 
-	constructor() {
+	constructor(props) {
 		super();
 
-		let temp = window.props;
-		let stationName = temp.stationName;
-
-		this.state = {
-			station: temp.stationData,
-			currentSongExists: false,
-		};
-
 		io.getSocket(socket => {
-			socket.emit("stations.join", stationName, res => {
+			socket.emit("stations.join", props.station.name, res => {
 				console.log(res);
 				if (res.status === 'success') {
-					this.setState({
-						station: { //TODO Refactor this to be better optimized
-							_id: res.data._id,
-							name: stationName,
-							displayName: res.data.displayName,
-							description: res.data.description,
-							privacy: res.data.privacy,
-							locked: res.data.locked,
-							partyMode: res.data.partyMode,
-							owner: res.data.owner,
-							privatePlaylist: res.data.privatePlaylist,
-							type: res.data.type,
-							paused: res.data.paused,
-						},
-						currentSong: (res.data.currentSong) ? res.data.currentSong : {},
-						currentSongExists: !!res.data.currentSong,
-					});
-
-					if (res.data.paused) this.player.pause(); //TODO Add async getPlayer here
-					else this.player.resume();
-
 					if (res.data.currentSong) {
 						res.data.currentSong.startedAt = res.data.startedAt;
 						res.data.currentSong.timePaused = res.data.timePaused;
 					}
-					this.changeSong(res.data.currentSong);
+					this.props.dispatch(changeSong(res.data.currentSong));
 				}
+
+				socket.on('event:songs.next', data => {
+					if (data.currentSong) {
+						data.currentSong.startedAt = res.data.startedAt;
+						data.currentSong.timePaused = res.data.timePaused;
+					}
+					this.props.dispatch(changeSong(data.currentSong));
+				});
+
+				socket.on('event:stations.pause', pausedAt => {
+					this.props.dispatch(pauseStation(pausedAt));
+				});
+
+				socket.on('event:stations.resume', data => {
+					this.props.dispatch(updateTimePaused(data.timePaused));
+					this.props.dispatch(resumeStation());
+				});
 			});
 		});
 
 		setInterval(() => {
-			if (this.state.currentSongExists) {
-				this.time.setTime(this.player.getTimeElapsed() / 1000);
-				this.seekerbar.setTimeElapsed(this.player.getTimeElapsed() / 1000);
+			if (this.props.songExists) {
+				this.props.dispatch(setTimeElapsed(this.props.station.paused, this.props.station.pausedAt)); // TODO Fix
 			}
 		}, 1000);
 	}
 
-	changeSong = (newSongObject) => {
-		let currentSongExists = !!newSongObject;
-		let state = {
-			currentSongExists,
-			currentSong: newSongObject,
-		};
-
-		if (currentSongExists) {
-			state.timeTotal = Time.formatTime(newSongObject.duration);
-			state.simpleSong = (newSongObject.likes === -1 && newSongObject.dislikes === -1);
-			if (state.simpleSong) {
-				state.currentSong.skipDuration = 0;
-				newSongObject.skipDuration = 0;// Do this better
-			}
-
-			this.seekerbar.setTime(newSongObject.duration);
-
-			this.player.playSong(newSongObject.songId, newSongObject.skipDuration, newSongObject.timePaused, newSongObject.startedAt, () => {
-				this.seekerbar.setTimeElapsed(this.player.getTimeElapsed() / 1000);
-			});
-		} else {
-			this.player.clearSong();
-		}
-
-		this.setState(state, () => {
-			this.getOwnRatings();
-		});
-	};
-
 	getOwnRatings = () => {
 		io.getSocket((socket) => {
 			if (!this.state.currentSongExists) return;
@@ -147,20 +125,28 @@ export default class Station extends Component {
 		return false;
 	};
 
-	changeId = () => {
-		this.player.playSong("jbZXYhjh3ms", 0, 0, Date.now());
-	};
-
 	addSongTemp = () => {
 		io.getSocket(socket => {
-			socket.emit('stations.addToQueue', this.state.station._id, '60ItHLz5WEA', data => {
+			socket.emit('stations.addToQueue', this.props.station.stationId, '60ItHLz5WEA', data => {
 				console.log("ATQ Res", data);
 			});
 		});
 	};
 
-	changeVolume = () => {
-		this.props.dispatch(changeVolume(32))
+	resumeStation = () => {
+		io.getSocket(socket => {
+			socket.emit('stations.resume', this.props.station.stationId, data => {
+
+			});
+		});
+	};
+
+	pauseStation = () => {
+		io.getSocket(socket => {
+			socket.emit('stations.pause', this.props.station.stationId, data => {
+
+			});
+		});
 	};
 
 	render() {
@@ -170,38 +156,36 @@ export default class Station extends Component {
 
 		return (
 			<main id="station">
-				<h1>{ this.state.station.displayName }</h1>
-
+				<h1>{ this.props.station.displayName }</h1>
 
-				<button onClick={ this.changeVolume }>Change volume</button>
+				{ (this.props.station.paused) ? <button onClick={ this.resumeStation }>Resume</button> : <button onClick={ this.pauseStation }>Pause</button>}
 
-				<button onClick={ this.changeId }>Change ID</button>
-				<button onClick={ () => { this.player.pause() } }>Pause</button>
-				<button onClick={ () => { this.player.resume() } }>Resume</button>
+				<button onClick={ this.addSongTemp }>Add song to queue TEMP</button>
 
-				<div className={(!this.state.currentSongExists) ? "hidden" : ""}>
+				<hr/>
+				<div className={(!this.props.songExists) ? "hidden" : ""}>
 					<Player onRef={ ref => (this.player = ref) }/>
 				</div>
 
-				{ (this.state.currentSongExists) ? (
+				{ (this.props.songExists) ? (
 				[
-					<span key="title">{ this.state.currentSong.title }</span>,
-					<br key="br1"/>,
-					<span key="artists">{ this.state.currentSong.artists.join(", ") }</span>,
-					<span key="time">
-						<Time onRef={ ref => (this.time = ref) }/> - { Time.formatTime(this.state.currentSong.duration) }
-					</span>,
-					<div key="seekerbar" className="seekerbar-container" style={{"width": "100%", "background-color": "yellow", "height": "20px", "display": "block"}}>
-						<Seekerbar onRef={ ref => (this.seekerbar = ref) }/>
+					<div key="content">
+						<h1>Title: { this.props.songTitle }</h1>
+						<br/>
+						Paused: { (this.props.station.paused) ? "true" : "false" }
+						<br/>
+						<span>Artists: { this.props.songArtists.join(", ") }</span>
+						<span key="time">
+							{ formatTime(this.props.songTimeElapsed) } - { formatTime(this.props.songDuration) }
+						</span>
+						<div key="seekerbar" className="seekerbar-container" style={{"width": "100%", "background-color": "yellow", "height": "20px", "display": "block"}}>
+							<Seekerbar/>
+						</div>
+						<VolumeSlider key="volumeSlider"/>
 					</div>,
 				]) : (
 					<h1>No song playing</h1>
 				) }
-
-
-				<VolumeSlider key="volumeSlider"/>,
-
-				<button onClick={ this.addSongTemp }>Add song to queue TEMP</button>
 			</main>
 		);
 	}