瀏覽代碼

Merge pull request #19 from Musare/staging

Beta Release Day 10 Part 2
Vos 8 年之前
父節點
當前提交
206bcddcc2

+ 1 - 0
backend/logic/actions/playlists.js

@@ -101,6 +101,7 @@ let lib = {
 			(next) => {
 				const { name, displayName, songs } = data;
 				db.models.playlist.create({
+					_id: utils.generateRandomString(17),//TODO Check if exists
 					displayName,
 					songs,
 					createdBy: userId,

+ 1 - 0
backend/logic/db/schemas/playlist.js

@@ -1,4 +1,5 @@
 module.exports = {
+	_id: { type: String, min: 17, max: 17, unique: true, index: true, required: true },
 	displayName: { type: String, min: 2, max: 32, required: true },
 	songs: { type: Array },
 	createdBy: { type: String, required: true },

+ 6 - 0
backend/logic/stations.js

@@ -56,6 +56,12 @@ module.exports = {
 		_this.getStation(stationId, (err, station) => {
 			if (!err) {
 				if (station) {
+					cache.hget('officialPlaylists', stationId, (err, playlist) => {
+						if (err || !playlist) {
+							_this.calculateOfficialPlaylistList(stationId, station.playlist, ()=>{});
+						}
+					});
+
 					let notification = notifications.subscribe(`stations.nextSong?id=${station._id}`, _this.skipStation(station._id), true);
 					if (!station.paused ) {
 						/*if (!station.startedAt) {

+ 3 - 3
frontend/App.vue

@@ -68,13 +68,13 @@
 				_this.username = username;
 				_this.userId = userId;
 			});
-			io.onConnect(() => {
+			io.onConnect(true, () => {
 				_this.socketConnected = true;
 			});
-			io.onConnectError(() => {
+			io.onConnectError(true, () => {
 				_this.socketConnected = false;
 			});
-			io.onDisconnect(() => {
+			io.onDisconnect(true, () => {
 				_this.socketConnected = false;
 			});
 			lofig.get('serverDomain', res => {

+ 10 - 3
frontend/components/Sidebars/SongsList.vue

@@ -96,14 +96,20 @@
 		font-weight: 600;
 	}
 
-	.media { padding: 0px 25px;}
+	.media { padding: 0 25px; }
 
 	.media-content .content {
-		height: 64px;
+		min-height: 64px;
 		display: flex;
 		align-items: center;
+	}
 
-		strong { word-break: break-word; }
+	.content p strong {
+		word-break: break-all;
+	}
+	
+	.content p small {
+		word-break: break-all;
 	}
 
 	.add-to-queue {
@@ -116,6 +122,7 @@
 		border: 0;
 		&:active, &:focus { border: 0; }
 	}
+	
 	.add-to-queue:focus { background: #029ce3; }
 
 	.media-right { line-height: 64px; }

+ 3 - 10
frontend/components/Station/Station.vue

@@ -16,7 +16,7 @@
 		<div v-show="noSong" class="no-song">
 			<h1>No song is currently playing</h1>
 			<h4 v-if='type === "community" && station.partyMode'>
-				<a href='#' class='no-song' @click='sidebars.queue = true'>Add a Song to the Queue</a>
+				<a href='#' class='no-song' @click='modals.addSongToQueue = true'>Add a Song to the Queue</a>
 			</h4>
 			<h4 v-if='type === "community" && !station.partyMode && $parent.userId === station.owner && !station.privatePlaylist'>
 				<a href='#' class='no-song' @click='sidebars.playlist = true'>Play a private playlist</a>
@@ -128,14 +128,7 @@
 		methods: {
 			editPlaylist: function (id) {
 				this.playlistBeingEdited = id;
-				this.toggleModal('editPlaylist');
-			},
-			toggleModal: function (type) {
-				if (type == 'addSongToQueue') this.modals.addSongToQueue = !this.modals.addSongToQueue;
-				else if (type == 'editPlaylist') this.modals.editPlaylist = !this.modals.editPlaylist;
-				else if (type == 'createPlaylist') this.modals.createPlaylist = !this.modals.createPlaylist;
-				else if (type == 'editStation') this.modals.editStation = !this.modals.editStation;
-				else if (type == 'report') this.modals.report = !this.modals.report;
+				this.modals.editPlaylist = !this.modals.editPlaylist;
 			},
 			toggleSidebar: function (type) {
 				Object.keys(this.sidebars).forEach(sidebar => {
@@ -170,7 +163,7 @@
 									local.player.seekTo(local.timeBeforePause / 1000, true);
 									local.player.pauseVideo();
 								}
-								if (event.data === 2 && !local.paused && !local.noSong) {
+								if (event.data === 2 && !local.paused && !local.noSong && local.getTimeElapsed() < local.currentSong.duration) {
 									local.player.seekTo(local.getTimeElapsed() / 1000 + local.currentSong.skipDuration, true);
 									local.player.playVideo();
 								}

+ 30 - 31
frontend/components/pages/Home.vue

@@ -14,6 +14,14 @@
 						<div class="media-left displayName">
 							<h5>{{ station.displayName }}</h5>
 						</div>
+						<div class="media-right">
+							<div v-if="station.privacy !== 'public'" title="This station is not visible to other users." class="station-status">
+								<i class='material-icons'>lock</i>
+							</div>
+							<div v-if="isOwner(station)" title="This is your station." class="station-status">
+								<i class='material-icons'>home</i>
+							</div>
+						</div>
 					</div>
 
 					<div class="content">
@@ -21,9 +29,6 @@
 					</div>
 				</div>
 				<a @click="this.$dispatch('joinStation', station._id)" href='#' class='absolute-a' v-link="{ path: '/official/' + station._id }"></a>
-				<div v-if="station.privacy !== 'public'" title="This station is not visible to other users." class="station-status">
-					<i class='material-icons'>lock</i>
-				</div>
 			</div>
 		</div>
 		<div class="group">
@@ -39,6 +44,14 @@
 						<div class="media-left displayName">
 							<h5>{{ station.displayName }}</h5>
 						</div>
+						<div class="media-right">
+							<div v-if="station.privacy !== 'public'" title="This station is not visible to other users." class="station-status">
+								<i class='material-icons'>lock</i>
+							</div>
+							<div v-if="isOwner(station)" title="This is your station." class="station-status">
+								<i class='material-icons'>home</i>
+							</div>
+						</div>
 					</div>
 
 					<div class="content">
@@ -46,12 +59,6 @@
 					</div>
 				</div>
 				<a @click="this.$dispatch('joinStation', station._id)" href='#' class='absolute-a' v-link="{ path: '/community/' + station._id }"></a>
-				<div v-if="station.privacy !== 'public'" title="This station is not visible to other users." class="station-status">
-					<i class='material-icons'>lock</i>
-				</div>
-				<div v-if="isOwner(station)" title="This is your station." class="station-status">
-					<i class='material-icons'>home</i>
-				</div>
 			</div>
 		</div>
 		<main-footer></main-footer>
@@ -174,22 +181,6 @@
 		html { font-size: 14px; }
 	}
 
-	.station-status {
-		width: 40px;
-		height: 40px;
-		position: absolute;
-		top: 0;
-		right: 0;
-		background-color: rgba(255, 255, 255, 1);
-		border-bottom-left-radius: 2px;
-		i {
-			font-size: 40px;
-			text-align: center;
-			line-height: 40px;
-			margin-left: 1px;
-		}
-	}
-
 	.group { min-height: 64px; }
 
 	.station-card {
@@ -237,16 +228,24 @@
 		display: inline-flex;
     	flex-direction: column;
 		overflow: hidden;
+
+		.content {
+			text-align: left;
+			word-wrap: break-word;
+		}
+
+		.media {
+			display: flex;
+    		align-items: center;
+
+			.station-status { line-height: 13px; }
+
+			h5 { margin: 0; }
+		}
 	}
 
 	.displayName {
 		word-wrap: break-word;
     	width: 80%;
 	}
-
-	.content {
-		text-align: left;
-		word-wrap: break-word;
-	}
-	
 </style>

+ 49 - 10
frontend/io.js

@@ -1,33 +1,55 @@
 let callbacks = [];
+let callbacksPersist = [];
 let onConnectCallbacks = [];
 let onDisconnectCallbacks = [];
 let onConnectErrorCallbacks = [];
+let onConnectCallbacksPersist = [];
+let onDisconnectCallbacksPersist = [];
+let onConnectErrorCallbacksPersist = [];
 
 export default {
 
 	ready: false,
 	socket: null,
 
-	getSocket: function (cb) {
-		if (this.ready) cb(this.socket);
-		else callbacks.push(cb);
+	getSocket: function () {
+		if (arguments[0] === true) {
+			if (this.ready) arguments[1](this.socket);
+			else callbacksPersist.push(arguments[1]);
+		} else {
+			if (this.ready) arguments[0](this.socket);
+			else callbacks.push(arguments[0]);
+		}
 	},
 
-	onConnect: (cb) => {
-		onConnectCallbacks.push(cb);
+	onConnect: function() {
+		if (arguments[0] === true) {
+			onConnectCallbacksPersist.push(arguments[1]);
+		} else onConnectCallbacks.push(arguments[0]);
 	},
 
-	onDisconnect: (cb) => {
-		onDisconnectCallbacks.push(cb);
+	onDisconnect: function() {
+		if (arguments[0] === true) {
+			onDisconnectCallbacksPersist.push(arguments[1]);
+		} else onDisconnectCallbacks.push(arguments[0]);
 	},
 
-	onConnectError: (cb) => {
-		onConnectErrorCallbacks.push(cb);
+	onConnectError: function() {
+		if (arguments[0] === true) {
+			onConnectErrorCallbacksPersist.push(arguments[1]);
+		} else onConnectErrorCallbacks.push(arguments[0]);
+	},
+
+	clear: () => {
+		onConnectCallbacks = [];
+		onDisconnectCallbacks = [];
+		onConnectErrorCallbacks = [];
+		callbacks = [];
 	},
 
 	removeAllListeners: function () {
 		Object.keys(this.socket._callbacks).forEach((id) => {
-			if (id.indexOf("$event:song") !== -1) {
+			if (id.indexOf("$event:") !== -1) {
 				delete this.socket._callbacks[id];
 			}
 		});
@@ -36,24 +58,41 @@ export default {
 	init: function (url) {
 		this.socket = window.socket = io(url);
 		this.socket.on('connect', () => {
+			console.log("IO: SOCKET CONNECTED");
 			onConnectCallbacks.forEach((cb) => {
 				cb();
 			});
+			onConnectCallbacksPersist.forEach((cb) => {
+				cb();
+			});
 		});
 		this.socket.on('disconnect', () => {
+			console.log("IO: SOCKET DISCONNECTED");
 			onDisconnectCallbacks.forEach((cb) => {
 				cb();
 			});
+			onDisconnectCallbacksPersist.forEach((cb) => {
+				cb();
+			});
 		});
 		this.socket.on('connect_error', () => {
+			console.log("IO: SOCKET CONNECT ERROR");
 			onConnectErrorCallbacks.forEach((cb) => {
 				cb();
 			});
+			onConnectErrorCallbacksPersist.forEach((cb) => {
+				cb();
+			});
 		});
 		this.ready = true;
 		callbacks.forEach(callback => {
 			callback(this.socket);
 		});
+
+		callbacksPersist.forEach(callback => {
+			callback(this.socket);
+		});
 		callbacks = [];
+		callbacksPersist = [];
 	}
 }

+ 1 - 0
frontend/main.js

@@ -42,6 +42,7 @@ router.beforeEach(transition => {
 	}
 	if (window.socket) {
 		io.removeAllListeners();
+		io.clear();
 	}
 	if (transition.to.loginRequired || transition.to.adminRequired) {
 		auth.getStatus((authenticated, role) => {