Procházet zdrojové kódy

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 před 7 roky
rodič
revize
a019484030

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

@@ -134,7 +134,9 @@ cache.sub('privatePlaylist.selected', data => {
 });
 });
 
 
 cache.sub('station.pause', stationId => {
 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 => {
 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"));
 		let volume = parseFloat(localStorage.getItem("volume"));
 		volume = (typeof volume === "number" && !isNaN(volume)) ? volume : 20;
 		volume = (typeof volume === "number" && !isNaN(volume)) ? volume : 20;
-		console.log("VOLUME", volume);
 		localStorage.setItem("volume", volume);
 		localStorage.setItem("volume", volume);
 		dispatch(initializeVolume(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 PropTypes from "prop-types";
 import { Redirect, Route } from "react-router-dom";
 import { Redirect, Route } from "react-router-dom";
 import { translate } from "react-i18next";
 import { translate } from "react-i18next";
+import { initializeStation } from "actions/station";
 
 
 import io from "io";
 import io from "io";
 
 
@@ -30,6 +31,10 @@ function clone(obj) {
 	loggedIn: state.user.get("loggedIn"),
 	loggedIn: state.user.get("loggedIn"),
 	role: state.user.get("role"),
 	role: state.user.get("role"),
 	authProcessed: state.user.get("authProcessed"),
 	authProcessed: state.user.get("authProcessed"),
+	station: {
+		stationId: state.station.get("id"),
+		name: state.station.get("name"),
+	},
 }))
 }))
 
 
 @translate(["general"], { wait: true })
 @translate(["general"], { wait: true })
@@ -88,30 +93,44 @@ export default class AuthRoute extends Component {
 	getStationData = () => {
 	getStationData = () => {
 		io.getSocket(socket => {
 		io.getSocket(socket => {
 			socket.emit("stations.findByName", this.state.stationName, res => {
 			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() {
 	render() {
 		const { auth, role, loggedIn, authProcessed, t } = this.props;
 		const { auth, role, loggedIn, authProcessed, t } = this.props;
-		const { stationName, waitingFor, receivedStationData, stationData } = this.state;
+		const { waitingFor, receivedStationData } = this.state;
 
 
 		if (this.state.continue) {
 		if (this.state.continue) {
 			return <PropsRoute props={ this.props } component={ this.props.component }/>
 			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
 				// 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 } />;
 				return <Route component={ this.props.component } />;
+			} else if (this.state.noStation) {
+				return <Redirect to={ "/" } />;
 			}
 			}
-			return <Redirect to={ "/" } />;
 		} else if (waitingFor === "auth" && authProcessed) {
 		} else if (waitingFor === "auth" && authProcessed) {
 			if (auth === "required") {
 			if (auth === "required") {
 				if (loggedIn) return <Route props={ this.props } component={ this.props.component } />;
 				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 { combineReducers } from "redux";
 import user from "reducers/user";
 import user from "reducers/user";
 import volume from "reducers/volume";
 import volume from "reducers/volume";
+import songPlayer from "reducers/songPlayer";
+import station from "reducers/station";
 
 
 export default combineReducers({
 export default combineReducers({
 	user,
 	user,
 	volume,
 	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 { connect } from "react-redux";
 
 
+import { pauseStation, unpauseStation } from "actions/station";
+
 const t = i18next.t;
 const t = i18next.t;
 let getPlayerCallbacks = [];
 let getPlayerCallbacks = [];
 
 
 @connect(state => ({
 @connect(state => ({
 	volume: state.volume.get("volume"),
 	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 {
 export default class Player extends Component {
 	static propTypes = {
 	static propTypes = {
@@ -27,10 +37,10 @@ export default class Player extends Component {
 				initializing: false,
 				initializing: false,
 				ready: false,
 				ready: false,
 				loading: false,
 				loading: false,
-				paused: true,
-				pausedAt: null, // Find better spot for this one
 			},
 			},
 		};
 		};
+
+		if (props.paused) this.pause();
 	}
 	}
 
 
 	componentDidMount() {
 	componentDidMount() {
@@ -50,70 +60,58 @@ export default class Player extends Component {
 		});
 		});
 	}
 	}
 
 
-	playSong(songId, skipDuration, timePaused, startedAt, cb) {
+	playSong() {
 		this.getPlayer((player) => {
 		this.getPlayer((player) => {
-			let pausedAt = (this.state.player.paused) ? Date.now() : null;
 			this.setState({
 			this.setState({
-				song: {
-					songId,
-					skipDuration,
-					timePaused,
-					startedAt,
-				},
 				player: {
 				player: {
 					...this.state.player,
 					...this.state.player,
-					pausedAt,
 					loading: true,
 					loading: true,
 				},
 				},
 			});
 			});
 
 
-			player.loadVideoById(songId, this.getProperVideoTime());
-			cb();
+			player.loadVideoById(this.props.songId, this.getProperVideoTime());
 		});
 		});
 	}
 	}
 
 
 	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;
 		} else return 0;
 	};
 	};
 
 
 	getTimeElapsed = () => {
 	getTimeElapsed = () => {
-		if (this.state.song) {
+		if (this.props.exists) {
 			// TODO Replace with Date.currently
 			// TODO Replace with Date.currently
 			let timePausedNow = 0;
 			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;
 		} else return 0;
 	};
 	};
 
 
 	pause() {
 	pause() {
 		this.getPlayer((player) => {
 		this.getPlayer((player) => {
-			if (this.state.player.paused) return;
-			this.setState({
-				player: {
-					...this.state.player,
-					paused: true,
-					pausedAt: Date.now(),
-				},
-			});
 			player.pauseVideo();
 			player.pauseVideo();
 		});
 		});
 	}
 	}
 
 
 	resume() {
 	resume() {
 		this.getPlayer((player) => {
 		this.getPlayer((player) => {
-			if (!this.state.player.paused) return;
-			this.setState({
-				player: {
-					...this.state.player,
-					paused: false,
-				},
-			});
 			player.playVideo();
 			player.playVideo();
 		});
 		});
 	}
 	}
 
 
+	mute() {
+		this.getPlayer((player) => {
+			player.mute();
+		});
+	}
+
+	unmute() {
+		this.getPlayer((player) => {
+			player.unMute();
+		});
+	}
+
 	initializePlayer = () => {
 	initializePlayer = () => {
 		// TODO Ensure YT.Player exists
 		// TODO Ensure YT.Player exists
 		if (this.state.player.ready || this.state.player.initializing) return;
 		if (this.state.player.ready || this.state.player.initializing) return;
@@ -135,7 +133,6 @@ export default class Player extends Component {
 							...this.state.player,
 							...this.state.player,
 							initializing: false,
 							initializing: false,
 							ready: true,
 							ready: true,
-							test: 1,
 						},
 						},
 					});
 					});
 
 
@@ -144,6 +141,8 @@ export default class Player extends Component {
 					});
 					});
 
 
 					this.player.setVolume(this.props.volume);
 					this.player.setVolume(this.props.volume);
+					if (this.props.muted) this.mute();
+					else this.unmute();
 				},
 				},
 				"onError": function(err) {
 				"onError": function(err) {
 					console.log("iframe error", err);
 					console.log("iframe error", err);
@@ -158,12 +157,12 @@ export default class Player extends Component {
 									loading: false,
 									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 (event.data === YT.PlayerState.PAUSED) {
-							if (!this.state.player.paused) {
+							if (!this.props.paused) {
 								player.seekTo(this.getProperVideoTime(), true);
 								player.seekTo(this.getProperVideoTime(), true);
 								player.playVideo();
 								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() {
 	render() {
 		return (
 		return (
 			<div id="player"/>
 			<div id="player"/>

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

@@ -1,6 +1,13 @@
 import React, { Component } from "react";
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 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 {
 export default class Seekerbar extends Component {
 	static propTypes = {
 	static propTypes = {
 		onRef: PropTypes.func,
 		onRef: PropTypes.func,
@@ -14,47 +21,31 @@ export default class Seekerbar extends Component {
 		super(props);
 		super(props);
 
 
 		this.state = {
 		this.state = {
-			timeTotal: 0,
-			timeElapsed: 0,
 			timeElapsedGuess: 0,
 			timeElapsedGuess: 0,
 			percentage: 0,
 			percentage: 0,
 		};
 		};
 
 
 		setInterval(() => {
 		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);
 		}, 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() {
 	render() {
 		return (
 		return (
 			<span style={{"width": this.state.percentage + "%", "background-color": "blue", "height": "100%", "display": "inline-block"}}/>
 			<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);
 		super(props);
 	}
 	}
 
 
-	changeVolumeHandler = (e) => {
-		let volume = e.target.value / 100;
+	changeVolumeHandler = (volume) => {
+		volume = volume / 100;
+		localStorage.setItem("volume", volume);
 		this.props.dispatch(changeVolume(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>
 				<h2>{ this.props.volume }. Muted: { (this.props.muted) ? "true" : "false" }</h2>
 				{
 				{
 					(this.props.muted) ? ([
 					(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/>,
 						<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>
 			</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 { translate, Trans } from "react-i18next";
 
 
 import Player from "./Player";
 import Player from "./Player";
-import Time from "./Time";
 import Seekerbar from "./Seekerbar";
 import Seekerbar from "./Seekerbar";
 import VolumeSlider from "./VolumeSlider";
 import VolumeSlider from "./VolumeSlider";
 
 
 import { changeVolume } from "actions/volume";
 import { changeVolume } from "actions/volume";
+import { changeSong, setTimeElapsed, timePaused } from "actions/songPlayer";
+import { pauseStation, resumeStation } from "actions/station";
 
 
 import { connect } from "react-redux";
 import { connect } from "react-redux";
 
 
 import io from "io";
 import io from "io";
 import config from "config";
 import config from "config";
+import {updateTimePaused} from "../../actions/songPlayer";
 
 
 const Aux = (props) => {
 const Aux = (props) => {
 	return props.children;
 	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 => ({
 @connect(state => ({
 	user: {
 	user: {
 		userId: state.user.get("userId"),
 		userId: state.user.get("userId"),
 		role: state.user.get("role"),
 		role: state.user.get("role"),
 	},
 	},
 	loggedIn: state.user.get("loggedIn"),
 	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 })
 @translate(["station"], { wait: true })
@@ -39,88 +59,46 @@ export default class Station extends Component {
 		t: () => {},
 		t: () => {},
 	};
 	};
 
 
-	constructor() {
+	constructor(props) {
 		super();
 		super();
 
 
-		let temp = window.props;
-		let stationName = temp.stationName;
-
-		this.state = {
-			station: temp.stationData,
-			currentSongExists: false,
-		};
-
 		io.getSocket(socket => {
 		io.getSocket(socket => {
-			socket.emit("stations.join", stationName, res => {
+			socket.emit("stations.join", props.station.name, res => {
 				console.log(res);
 				console.log(res);
 				if (res.status === 'success') {
 				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) {
 					if (res.data.currentSong) {
 						res.data.currentSong.startedAt = res.data.startedAt;
 						res.data.currentSong.startedAt = res.data.startedAt;
 						res.data.currentSong.timePaused = res.data.timePaused;
 						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(() => {
 		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);
 		}, 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 = () => {
 	getOwnRatings = () => {
 		io.getSocket((socket) => {
 		io.getSocket((socket) => {
 			if (!this.state.currentSongExists) return;
 			if (!this.state.currentSongExists) return;
@@ -147,20 +125,28 @@ export default class Station extends Component {
 		return false;
 		return false;
 	};
 	};
 
 
-	changeId = () => {
-		this.player.playSong("jbZXYhjh3ms", 0, 0, Date.now());
-	};
-
 	addSongTemp = () => {
 	addSongTemp = () => {
 		io.getSocket(socket => {
 		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);
 				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() {
 	render() {
@@ -170,38 +156,36 @@ export default class Station extends Component {
 
 
 		return (
 		return (
 			<main id="station">
 			<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) }/>
 					<Player onRef={ ref => (this.player = ref) }/>
 				</div>
 				</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>,
 					</div>,
 				]) : (
 				]) : (
 					<h1>No song playing</h1>
 					<h1>No song playing</h1>
 				) }
 				) }
-
-
-				<VolumeSlider key="volumeSlider"/>,
-
-				<button onClick={ this.addSongTemp }>Add song to queue TEMP</button>
 			</main>
 			</main>
 		);
 		);
 	}
 	}