浏览代码

Added/converted functionality for adding playlists to the queue.

KrisVos130 7 年之前
父节点
当前提交
8fd6f0dbd5

+ 35 - 6
frontend/app/js/ducks/stationInfo.js

@@ -1,4 +1,4 @@
-import { Map, List } from "immutable";
+import { Map, List, fromJS } from "immutable";
 
 const JOIN = "STATION_INFO::JOIN";
 const LEAVE = "STATION_INFO::LEAVE";
@@ -12,6 +12,8 @@ const QUEUE_INDEX = "STATION_INFO::QUEUE_INDEX";
 const QUEUE_UPDATE = "STATION_INFO::QUEUE_UPDATE";
 const PAUSE = "STATION_INFO::PAUSE";
 const RESUME = "STATION_INFO::RESUME";
+const SELECT_PLAYLIST = "STATION_INFO::SELECT_PLAYLIST";
+const SELECT_PLAYLIST_QUEUE = "STATION_INFO::SELECT_PLAYLIST_QUEUE";
 
 function joinStation(station) {
 	return {
@@ -94,6 +96,20 @@ function resume() {
 	}
 }
 
+function selectPlaylist(playlistId) {
+	return {
+		type: SELECT_PLAYLIST,
+		playlistId,
+	}
+}
+
+function selectPlaylistQueue(playlistId) {
+	return {
+		type: SELECT_PLAYLIST_QUEUE,
+		playlistId,
+	}
+}
+
 
 
 const initialState = Map({
@@ -110,6 +126,7 @@ const initialState = Map({
 	"userCount": 0,
 	"songList": List([]),
 	"privatePlaylist": "",
+	"privatePlaylistQueue": "",
 });
 
 function reducer(state = initialState, action) {
@@ -148,16 +165,16 @@ function reducer(state = initialState, action) {
 			ownerId,
 			paused,
 			mode: (getModeTemp(action.station.partyMode, action.station.locked)),
-			userList: List(action.station.userList),
+			userList: fromJS(action.station.userList),
 			userCount,
-			songList: List(action.station.songList),
+			songList: fromJS(action.station.songList),
 			privatePlaylist: action.station.privatePlaylist,
 		});
 	case LEAVE:
 		return initialState;
 	case USER_LIST_UPDATE:
 		return state.merge({
-			userList: List(action.userList),
+			userList: fromJS(action.userList),
 		});
 	case USER_COUNT_UPDATE:
 		return state.merge({
@@ -181,11 +198,11 @@ function reducer(state = initialState, action) {
 		});
 	case QUEUE_INDEX:
 		return state.merge({
-			songList: List(action.songList),
+			songList: fromJS(action.songList),
 		});
 	case QUEUE_UPDATE:
 		return state.merge({
-			songList: List(action.songList),
+			songList: fromJS(action.songList),
 		});
 	case PAUSE:
 		return state.merge({
@@ -195,6 +212,14 @@ function reducer(state = initialState, action) {
 		return state.merge({
 			paused: false,
 		});
+	case SELECT_PLAYLIST:
+		return state.merge({
+			privatePlaylist: action.playlistId,
+		});
+	case SELECT_PLAYLIST_QUEUE:
+		return state.merge({
+			privatePlaylistQueue: action.playlistId,
+		});
 	}
 	return state;
 }
@@ -212,6 +237,8 @@ const actionCreators = {
 	queueUpdate,
 	pause,
 	resume,
+	selectPlaylist,
+	selectPlaylistQueue,
 };
 
 const actionTypes = {
@@ -227,6 +254,8 @@ const actionTypes = {
 	QUEUE_UPDATE,
 	PAUSE,
 	RESUME,
+	SELECT_PLAYLIST,
+	SELECT_PLAYLIST_QUEUE,
 };
 
 export {

+ 0 - 1
frontend/app/js/ducks/stationPlaylists.js

@@ -66,7 +66,6 @@ function reducer(state = initialState, action) {
 	function updatePlaylist(playlistId, updater) {
 		return state.update(
 			state.findIndex(function(playlist) {
-				console.log(55544, playlist);
 				return playlist.get("playlistId") === playlistId;
 			}),
 			updater

+ 4 - 0
frontend/app/js/views/Station/PlayerDebug.jsx

@@ -16,6 +16,7 @@ import { connect } from "react-redux";
 	exists: state.station.currentSong.get("songId") !== "",
 	paused: state.station.info.get("paused"),
 	mode: state.station.info.get("mode"),
+	privatePlaylistQueue: state.station.info.get("privatePlaylistQueue"),
 }))
 export default class PlayerDebug extends Component {
 	static propTypes = {
@@ -57,6 +58,9 @@ export default class PlayerDebug extends Component {
 				<b>Paused at: </b> { this.props.pausedAt } <br/>
 				<b>Started at: </b> { this.props.startedAt } <br/>
 				<b>Exists: </b> { this.props.exists.toString() } <br/>
+				<h3>Adding to queue</h3>
+				<b>Playlist to queue: </b> { this.props.privatePlaylistQueue } <br/>
+
 				<hr/>
 			</div>
 		);

+ 9 - 7
frontend/app/js/views/Station/Views/Queue/PlaylistItem.jsx

@@ -1,26 +1,28 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 
+import { actionCreators as stationInfoActionCreators } from "ducks/stationInfo";
+import { bindActionCreators } from "redux";
+
 import { connect } from "react-redux";
 
 @connect(state => ({
 	station: {
-		playlistSelectedId: state.station.info.get("playlistSelected"),
+		playlistSelectedId: state.station.info.get("privatePlaylistQueue"),
 	},
+}),
+(dispatch) => ({
+	onSelectPlaylist: bindActionCreators(stationInfoActionCreators.selectPlaylistQueue, dispatch),
 }))
 export default class PlaylistItem extends Component {
 	constructor(props) {
 		super(props);
 	}
 
-	selectPlaylist = (playlistId) => {
-		this.props.dispatch(selectPlaylist(playlistId));
-	}
-
 	getPlaylistAction = (playlistId) => {
 		if (playlistId === this.props.station.playlistSelectedId) {
 			return <span>SELECTED</span>;
-		} else return <span onClick={ () => { this.selectPlaylist(playlistId); } }>SELECT</span>;
+		} else return <span onClick={ () => { this.props.onSelectPlaylist(playlistId); } }>SELECT</span>;
 	}
 
 	render() {
@@ -28,7 +30,7 @@ export default class PlaylistItem extends Component {
 
 		return (
 			<li style={{color: "black"}}>
-				{ playlist.get("displayName") } - { this.getPlaylistAction(playlist.get("_id")) }
+				{ playlist.get("displayName") } - { this.getPlaylistAction(playlist.get("playlistId")) }
 			</li>
 		);
 	}

+ 1 - 1
frontend/app/js/views/Station/Views/Queue/PlaylistList.jsx

@@ -16,7 +16,7 @@ export default class PlaylistList extends Component {
 	}
 
 	render() {
-		const { playlists } = this.props;
+		const { playlists } = this.props.station;
 
 		return (
 			<ul>

+ 0 - 27
frontend/app/js/views/Station/Views/Queue/index.jsx

@@ -37,33 +37,6 @@ import io from "io";
 export default class QueueList extends Component {
 	constructor(props) {
 		super(props);
-
-		this.state = {
-			playlists: [],
-		};
-
-		io.getSocket((socket) => {
-			socket.emit('playlists.indexForUser', res => {
-				if (res.status === 'success') this.setState({
-					playlists: res.data,
-				});
-			});
-
-			socket.on('event:playlist.create', () => {
-				socket.emit('playlists.indexForUser', res => {
-					if (res.status === 'success') this.setState({
-						playlists: res.data,
-					});
-				});
-			});
-			socket.on('event:playlist.delete', () => {
-				socket.emit('playlists.indexForUser', res => {
-					if (res.status === 'success') this.setState({
-						playlists: res.data,
-					});
-				});
-			});
-		});
 	}
 
 	addSongToQueueCallback = (songId) => {

+ 64 - 89
frontend/app/js/views/Station/index.jsx

@@ -1,6 +1,7 @@
 import React, { Component } from "react";
 import { NavLink } from "react-router-dom";
 import { Map, List } from "immutable";
+import async from "async";
 
 import PropTypes from "prop-types";
 import { translate, Trans } from "react-i18next";
@@ -45,13 +46,16 @@ import config from "config";
 		title: state.station.currentSong.get("title"),
 		artists: state.station.currentSong.get("artists"),
 	},
+	playlists: state.station.playlists,
 	station: {
 		stationId: state.station.info.get("stationId"),
 		name: state.station.info.get("name"),
 		displayName: state.station.info.get("displayName"),
 		type: state.station.info.get("type"),
+		songList: state.station.info.get("songList"),
 		paused: state.station.info.get("paused"),
 		ownerId: state.station.info.get("ownerId"),
+		privatePlaylistQueue: state.station.info.get("privatePlaylistQueue"),
 	},/*
 	selectedPlaylistObject: {
 		addedSongId: state.playlistQueue.get("addedSongId"),
@@ -97,6 +101,7 @@ export default class Station extends Component {
 			timeElapsedInterval: setInterval(() => {
 				props.onTimeElapsedUpdate();
 			}, 500),
+			automaticallyAddedSongId: null,
 		};
 		/*this.state = {
 			mode: this.getModeTemp(props.partyEnabled, props.queueLocked),
@@ -136,7 +141,7 @@ export default class Station extends Component {
 					});
 
 					socket.on("event:songs.next", data => {
-						//this.addTopToQueue();
+						this.addTopToQueue();
 						if (data.currentSong) {
 							let song = {
 								songId: data.currentSong.songId,
@@ -244,111 +249,81 @@ export default class Station extends Component {
 				}
 			});
 		});
-
-		/*setInterval(() => {
-			if (this.props.song.exists) {
-				this.props.dispatch(setTimeElapsed(this.props.station.paused, this.props.station.pausedAt)); // TODO Fix
-			}
-		}, 1000);*/
 	}
 
 	componentWillUnmount() {
 		clearInterval(this.state.timeElapsedInterval);
 	}
 
-	/*isInQueue = (songId, cb) => {
+	addTopToQueue = () => {
+		const randomIdentifier = Math.floor(Math.random() * 10000000000);
+		console.log("ADDTOPTOQUEUE", randomIdentifier);
+		const automaticallyAddedSongId = this.state.automaticallyAddedSongId;
+		const privatePlaylistQueue = this.props.station.privatePlaylistQueue;
 		io.getSocket((socket) => {
-			socket.emit('stations.getQueue', this.props.stationId, data => {
-				if (data.status === 'success') {
-					data.queue.forEach((song) => {
-						if (song._id === songId) {
-							return cb(true);
+			async.waterfall([
+				(next) => {
+					if (this.state.mode === "normal") return next("Mode invalid."); //
+					if (!privatePlaylistQueue) return next("No playlist selected."); // There hasn't been any playlist that has been selected
+					if (!automaticallyAddedSongId) return next(); // There hasn't been any song that automatically got added to the queue
+					//if (this.props.song.exists && automaticallyAddedSongId === this.props.song.songId) return next("Previously automatically added song is still playing."); // The song that was previously automatically added is already currently playing
+					let alreadyAdded = false;
+					this.props.station.songList.forEach((song) => {
+						if (automaticallyAddedSongId === song.get("songId")) alreadyAdded = true;
+					});
+					if (alreadyAdded) return next("Previously automatically added song is still in the queue."); // The song that was automatically added previously is already currently in the queue
+					return next();
+				},
+				(next) => {
+					const playlist = this.props.playlists.find((playlist) => {
+						return privatePlaylistQueue === playlist.get("playlistId");
+					});
+					if (!playlist) return next("Selected playlist isn't found.");
+					const song = playlist.get("songs").get(0);
+					if (!song) return next("Top song couldn't be found.");
+					if (song.get("duration") > 15 * 60) return next("BOTTOM");
+					const songId = song.get("songId");
+					this.setState({
+						...this.state,
+						automaticallyAddedSongId: songId,
+					});
+					socket.emit("stations.addToQueue", this.props.station.stationId, songId, data => {
+						return next(null, data, songId);
+					});
+				},
+				(data, songId, next) => {
+					if (data.status !== "success") return next("Song couldn't be added to the queue.");
+					this.moveToBottom(privatePlaylistQueue, songId, (data) => {
+						return next(null, data);
+					});
+				},
+				(data, next) => {
+					if (data.status !== "success") return next("Song couldn't be moved to the bottom of the playlist.");
+					return next();
+				},
+			], (err, res) => {
+				if (err) console.log("ADDTOPTOQUEUE ERROR", randomIdentifier, err, res);
+				else console.log("ADDTOPTOQUEUE SUCCESS", randomIdentifier);
+ 				if (err === "BOTTOM") {
+					this.moveToBottom(privatePlaylistQueue, res.songId, (data) => {
+						if (data.status === "success" && res.status !== "success") {
+							setTimeout(() => {
+								this.addTopToQueue();
+							}, 2000);
 						}
 					});
 				}
-
-				return cb(false);
 			});
 		});
-	};*/
-
-	/*checkIfCanAdd = (cb) => {
-		if (this.state.mode === "normal") return cb(false);
-		let playlistId = this.props.selectedPlaylistObject.selectedPlaylistId;
-		let songId = this.props.selectedPlaylistObject.addedSongId;
-		console.log(playlistId, songId, this.props.song.songId);
-		if (playlistId) {
-			if (songId === this.props.song.songId) return cb(true);
-			else if (songId === null) return cb(true);
-			else {
-				this.isInQueue(songId, (res) => {
-					return cb(res);
-				});
-			}
-		}
-	}*/
-
-	/*addTopToQueue = () => {
-		console.log("ADD TOP TO QUEUE!!!");
-		this.checkIfCanAdd((can) => {
-			if (!can) return;
-			let playlistId = this.props.selectedPlaylistObject.selectedPlaylistId;
-			console.log(can);
-			io.getSocket((socket) => {
-				socket.emit('playlists.getFirstSong', this.props.selectedPlaylistObject.selectedPlaylistId, data => {
-					if (data.status === 'success') {
-						let songId = data.song.songId;
-						if (data.song.duration < 15 * 60) {
-							this.props.dispatch(addSong(songId));
-
-							socket.emit('stations.addToQueue', this.props.station.stationId, songId, data2 => {
-								if (data2.status === 'success') {
-									this.moveToBottom(playlistId, songId, (data3) => {
-										if (data3.status === 'success') {
-										}
-									});
-								} else {
-									this.messages.clearAddError("Could not automatically add top song of playlist to queue.", data2.message);
-								}
-							});
-						} else {
-							this.messages.clearAddError("Top song in playlist was too long to be added. Moving to the next song.");
-							this.moveToBottom(playlistId, songId, (data3) => {
-								if (data3.status === 'success') {
-									setTimeout(() => {
-										this.addTopToQueue();
-									}, 2000);
-								}
-							});
-						}
-					}
-				});
-			});
-		});
-	};*/
+	};
 
-	/*moveToBottom = (playlistId, songId, cb) => {
+	moveToBottom = (playlistId, songId, cb) => {
 		io.getSocket((socket) => {
-			socket.emit('playlists.moveSongToBottom', playlistId, songId, data => {
+			socket.emit("playlists.moveSongToBottom", playlistId, songId, data => {
 				cb(data);
 			});
 		});
-	}*/
-
-	/*getModeTemp = (partyEnabled, queueLocked) => {
-		// If party enabled
-		// If queue locked
-		// Mode is DJ
-		// If queue not locked
-		// Mode party
-		// If party not enabled
-		// Mode is normal
-
-		if (partyEnabled) {
-			if (queueLocked) return "dj";
-			else return "party";
-		} else return "normal";
-	}*/
+	}
 
 	fetchOwnRatings = () => {
 		io.getSocket((socket) => {