瀏覽代碼

Merge branch 'polishing' into manage-station

Kristian Vos 3 年之前
父節點
當前提交
023edcbbdc

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

@@ -18,7 +18,7 @@ CacheModule.runJob("SUB", {
 	channel: "playlist.create",
 	cb: playlist => {
 		WSModule.runJob("SOCKETS_FROM_USER", { userId: playlist.createdBy }, this).then(sockets =>
-			sockets.forEach(socket => socket.dispatch("d", { data: { playlist } }))
+			sockets.forEach(socket => socket.dispatch("event:playlist.created", { data: { playlist } }))
 		);
 
 		if (playlist.privacy === "public")

+ 9 - 4
frontend/src/App.vue

@@ -451,12 +451,17 @@ a {
 	}
 }
 
+.tippy-tooltip.info-theme {
+	font-size: 12px;
+	letter-spacing: 1px;
+}
+
 .tippy-tooltip.confirm-theme {
 	background-color: var(--red);
 	padding: 5px 10px;
 	a {
 		color: var(--white);
-		font-size: 14px;
+		font-size: 15px;
 		font-weight: 600;
 		&:hover,
 		&:focus {
@@ -466,7 +471,7 @@ a {
 }
 
 .tippy-tooltip.songActions-theme {
-	font-size: 14px;
+	font-size: 15px;
 	padding: 5px 10px;
 	border: 1px solid var(--light-grey-3);
 	box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
@@ -498,7 +503,7 @@ a {
 			filter: brightness(90%);
 		}
 
-		&:not(:first-of-type) {
+		&:not(:first) {
 			margin-left: 5px;
 		}
 	}
@@ -574,7 +579,7 @@ a {
 }
 
 .tippy-tooltip.addToPlaylist-theme {
-	font-size: 14px;
+	font-size: 15px;
 	padding: 5px;
 	border: 1px solid var(--light-grey-3);
 	box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);

+ 51 - 31
frontend/src/components/AddToPlaylistDropdown.vue

@@ -48,7 +48,7 @@
 </template>
 
 <script>
-import { mapGetters } from "vuex";
+import { mapGetters, mapState, mapActions } from "vuex";
 import Toast from "toasters";
 
 export default {
@@ -62,40 +62,59 @@ export default {
 			default: "left"
 		}
 	},
-	data() {
-		return {
-			playlists: []
-		};
+	computed: {
+		...mapGetters({
+			socket: "websockets/getSocket"
+		}),
+		...mapState({
+			fetchedPlaylists: state => state.user.playlists.fetchedPlaylists
+		}),
+		playlists: {
+			get() {
+				return this.$store.state.user.playlists.playlists;
+			},
+			set(playlists) {
+				this.$store.commit("user/playlists/setPlaylists", playlists);
+			}
+		}
 	},
-	computed: mapGetters({
-		socket: "websockets/getSocket"
-	}),
 	mounted() {
-		this.socket.dispatch("playlists.indexMyPlaylists", false, res => {
-			if (res.status === "success") {
-				this.playlists = res.data.playlists;
-			}
-		});
+		if (!this.fetchedPlaylists)
+			this.socket.dispatch("playlists.indexMyPlaylists", false, res => {
+				if (res.status === "success")
+					this.setPlaylists(res.data.playlists);
+			});
 
-		this.socket.on("event:playlist.created", res => {
-			this.playlists.push(res.data.playlist);
-		});
+		this.socket.on(
+			"event:playlist.created",
+			res => this.playlists.push(res.data.playlist),
+			{ replaceable: true }
+		);
 
-		this.socket.on("event:playlist.deleted", res => {
-			this.playlists.forEach((playlist, index) => {
-				if (playlist._id === res.data.playlistId) {
-					this.playlists.splice(index, 1);
-				}
-			});
-		});
+		this.socket.on(
+			"event:playlist.deleted",
+			res => {
+				this.playlists.forEach((playlist, index) => {
+					if (playlist._id === res.data.playlistId) {
+						this.playlists.splice(index, 1);
+					}
+				});
+			},
+			{ replaceable: true }
+		);
 
-		this.socket.on("event:playlist.displayName.updated", res => {
-			this.playlists.forEach((playlist, index) => {
-				if (playlist._id === res.data.playlistId) {
-					this.playlists[index].displayName = res.data.displayName;
-				}
-			});
-		});
+		this.socket.on(
+			"event:playlist.displayName.updated",
+			res => {
+				this.playlists.forEach((playlist, index) => {
+					if (playlist._id === res.data.playlistId) {
+						this.playlists[index].displayName =
+							res.data.displayName;
+					}
+				});
+			},
+			{ replaceable: true }
+		);
 	},
 	methods: {
 		toggleSongInPlaylist(playlistIndex) {
@@ -141,7 +160,8 @@ export default {
 				playlist.songs.map(song => song._id).indexOf(this.song._id) !==
 				-1
 			);
-		}
+		},
+		...mapActions("user/playlists", ["setPlaylists"])
 	}
 };
 </script>

+ 1 - 1
frontend/src/components/PlaylistItem.vue

@@ -8,7 +8,7 @@
 					v-if="playlist.privacy === 'private'"
 					class="private-playlist-icon material-icons"
 					content="This playlist is not visible to other users."
-					v-tippy
+					v-tippy="{ theme: 'info' }"
 					>lock</i
 				>
 			</p>

+ 18 - 21
frontend/src/components/Queue.vue

@@ -27,6 +27,7 @@
 					:class="{
 						'item-draggable': isAdminOnly() || isOwnerOnly()
 					}"
+					:disabled-actions="[]"
 				>
 					<div
 						v-if="isAdminOnly() || isOwnerOnly()"
@@ -105,7 +106,7 @@
 						station.type === 'official')
 			"
 			content="Login to add songs to queue"
-			v-tippy
+			v-tippy="{ theme: 'info' }"
 		>
 			<i class="material-icons icon-with-button">queue</i>
 			<span class="optional-desktop-only-text"> Add Song To Queue </span>
@@ -240,21 +241,12 @@ export default {
 				},
 				res => {
 					new Toast({ content: res.message, timeout: 4000 });
-					if (res.status !== "success") {
-						if (this.sector === "station") {
-							this.repositionSongInListStation({
-								...moved.element,
-								newIndex: moved.oldIndex,
-								oldIndex: moved.newIndex
-							});
-						} else if (this.sector === "manageStation") {
-							this.repositionSongInListManageStation({
-								...moved.element,
-								newIndex: moved.oldIndex,
-								oldIndex: moved.newIndex
-							});
-						}
-					}
+					if (res.status !== "success")
+						this.repositionSongInList({
+							...moved.element,
+							newIndex: moved.oldIndex,
+							oldIndex: moved.newIndex
+						});
 				}
 			);
 		},
@@ -276,11 +268,16 @@ export default {
 				}
 			});
 		},
-		...mapActions("modals/manageStation", {
-			repositionSongInListManageStation: "repositionSongInList"
-		}),
-		...mapActions("station", {
-			repositionSongInListStation: "repositionSongInList"
+		...mapActions({
+			repositionSongInList(dispatch, payload) {
+				if (this.sector === "manageStation")
+					return dispatch(
+						"modals/manageStation/repositionSongInList",
+						payload
+					);
+
+				return dispatch("station/repositionSongInList", payload);
+			}
 		}),
 		...mapActions("modalVisibility", ["openModal"]),
 		...mapActions({

+ 2 - 1
frontend/src/components/SongItem.vue

@@ -24,7 +24,7 @@
 						v-if="song.status === 'verified'"
 						class="material-icons verified-song"
 						content="Verified Song"
-						v-tippy
+						v-tippy="{ theme: 'info' }"
 					>
 						check_circle
 					</i>
@@ -307,6 +307,7 @@ export default {
 		.song-title {
 			display: flex;
 			flex-direction: row;
+
 			.verified-song {
 				margin-left: 5px;
 			}

+ 2 - 2
frontend/src/components/modals/ManageStation/Tabs/Playlists.vue

@@ -121,7 +121,7 @@
 								v-if="isExcluded(playlist._id)"
 								class="material-icons stop-icon"
 								content="This playlist is blacklisted in this station"
-								v-tippy
+								v-tippy="{ theme: 'info' }"
 								>play_disabled</i
 							>
 							<confirm
@@ -321,7 +321,7 @@
 									v-if="isExcluded(playlist._id)"
 									class="material-icons stop-icon"
 									content="This playlist is blacklisted in this station"
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 									>play_disabled</i
 								> -->
 								<i

+ 2 - 2
frontend/src/components/modals/ManageStation/Tabs/Settings.vue

@@ -187,7 +187,7 @@
 					<button
 						class="blue"
 						content="Can not be changed on official stations."
-						v-tippy
+						v-tippy="{ theme: 'info' }"
 					>
 						<i class="material-icons">playlist_play</i>
 						Playlist
@@ -240,7 +240,7 @@
 					<button
 						class="blue"
 						content="Can not be changed on official stations."
-						v-tippy
+						v-tippy="{ theme: 'info' }"
 					>
 						<i class="material-icons">shuffle</i>
 						Random

+ 8 - 1
frontend/src/components/modals/ManageStation/index.vue

@@ -112,6 +112,7 @@
 								v-if="isOwnerOrAdmin()"
 								class="button is-default"
 								:class="{ selected: tab === 'settings' }"
+								ref="settings-tab"
 								@click="showTab('settings')"
 							>
 								Settings
@@ -120,6 +121,7 @@
 								v-if="isAllowedToParty() || isOwnerOrAdmin()"
 								class="button is-default"
 								:class="{ selected: tab === 'playlists' }"
+								ref="playlists-tab"
 								@click="showTab('playlists')"
 							>
 								Playlists
@@ -635,7 +637,6 @@ export default {
 			);
 		},
 		...mapActions("modals/manageStation", [
-			"showTab",
 			"editStation",
 			"setIncludedPlaylists",
 			"setExcludedPlaylists",
@@ -646,6 +647,12 @@ export default {
 			"updateStationPaused",
 			"updateCurrentSong"
 		]),
+		...mapActions({
+			showTab(dispatch, payload) {
+				this.$refs[`${payload}-tab`].scrollIntoView();
+				return dispatch("modals/manageStation/showTab", payload);
+			}
+		}),
 		...mapActions("modalVisibility", ["openModal", "closeModal"]),
 		...mapActions("user/playlists", ["editPlaylist"])
 	}

+ 4 - 1
frontend/src/components/modals/ViewReport.vue

@@ -24,7 +24,10 @@
 					/>
 					<br />
 					<strong>Time of report:</strong>
-					<span :content="report.createdAt" v-tippy>
+					<span
+						:content="report.createdAt"
+						v-tippy="{ theme: 'info' }"
+					>
 						{{
 							formatDistance(
 								new Date(report.createdAt),

+ 11 - 7
frontend/src/pages/Admin/tabs/Reports.vue

@@ -28,13 +28,17 @@
 							/>
 						</td>
 						<td>
-							<span :content="report.createdAt" v-tippy>{{
-								formatDistance(
-									new Date(report.createdAt),
-									new Date(),
-									{ addSuffix: true }
-								)
-							}}</span>
+							<span
+								:content="report.createdAt"
+								v-tippy="{ theme: 'info' }"
+								>{{
+									formatDistance(
+										new Date(report.createdAt),
+										new Date(),
+										{ addSuffix: true }
+									)
+								}}</span
+							>
 						</td>
 						<td>
 							<span>{{ report.description }}</span>

+ 14 - 12
frontend/src/pages/Home.vue

@@ -107,7 +107,9 @@
 											v-if="station.type === 'official'"
 											class="material-icons verified-station"
 											content="Verified Station"
-											v-tippy
+											v-tippy="{
+												theme: 'info'
+											}"
 										>
 											check_circle
 										</i>
@@ -143,14 +145,14 @@
 											"
 											class="homeIcon material-icons"
 											content="This is your station."
-											v-tippy
+											v-tippy="{ theme: 'info' }"
 											>home</i
 										>
 										<i
 											v-if="station.privacy === 'private'"
 											class="privateIcon material-icons"
 											content="This station is not visible to other users."
-											v-tippy
+											v-tippy="{ theme: 'info' }"
 											>lock</i
 										>
 										<i
@@ -159,7 +161,7 @@
 											"
 											class="unlistedIcon material-icons"
 											content="Unlisted Station"
-											v-tippy
+											v-tippy="{ theme: 'info' }"
 											>link</i
 										>
 									</div>
@@ -173,7 +175,7 @@
 									"
 									class="material-icons"
 									content="Station Paused"
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 									>pause</i
 								>
 								<i
@@ -216,7 +218,7 @@
 											? 'Station in Party mode'
 											: 'Station in Playlist mode'
 									"
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 									>{{
 										station.partyMode
 											? "emoji_people"
@@ -321,7 +323,7 @@
 									v-if="station.type === 'official'"
 									class="material-icons verified-station"
 									content="Verified Station"
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 								>
 									check_circle
 								</i>
@@ -355,21 +357,21 @@
 									"
 									class="homeIcon material-icons"
 									content="This is your station."
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 									>home</i
 								>
 								<i
 									v-if="station.privacy === 'private'"
 									class="privateIcon material-icons"
 									content="This station is not visible to other users."
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 									>lock</i
 								>
 								<i
 									v-if="station.privacy === 'unlisted'"
 									class="unlistedIcon material-icons"
 									content="Unlisted Station"
-									v-tippy
+									v-tippy="{ theme: 'info' }"
 									>link</i
 								>
 							</div>
@@ -380,7 +382,7 @@
 							v-if="station.paused && station.currentSong.title"
 							class="material-icons"
 							content="Station Paused"
-							v-tippy
+							v-tippy="{ theme: 'info' }"
 							>pause</i
 						>
 						<i
@@ -417,7 +419,7 @@
 									? 'Station in Party mode'
 									: 'Station in Playlist mode'
 							"
-							v-tippy
+							v-tippy="{ theme: 'info' }"
 							>{{
 								station.partyMode
 									? "emoji_people"

+ 1 - 1
frontend/src/pages/Profile/index.vue

@@ -63,7 +63,7 @@
 						<i
 							class="material-icons"
 							content="Account Creation Date"
-							v-tippy
+							v-tippy="{ theme: 'info' }"
 							>calendar_today</i
 						>
 						<p>{{ user.createdAt }}</p>

+ 1 - 1
frontend/src/pages/Station/Sidebar/Playlists.vue

@@ -24,7 +24,7 @@
 							v-if="isExcluded(playlist._id)"
 							class="material-icons stop-icon"
 							content="This playlist is blacklisted in this station"
-							v-tippy
+							v-tippy="{ theme: 'info' }"
 							>play_disabled</i
 						>
 						<i

+ 1 - 1
frontend/src/pages/Station/Sidebar/index.vue

@@ -27,7 +27,7 @@
 				v-else
 				class="button is-default"
 				content="Login to manage playlists"
-				v-tippy
+				v-tippy="{ theme: 'info' }"
 			>
 				My Playlists
 			</button>

+ 26 - 13
frontend/src/pages/Station/index.vue

@@ -102,7 +102,7 @@
 												? 'Station in Party mode'
 												: 'Station in Playlist mode'
 										"
-										v-tippy
+										v-tippy="{ theme: 'info' }"
 										>{{
 											station.partyMode
 												? "emoji_people"
@@ -339,7 +339,7 @@
 										v-else
 										class="button is-primary disabled"
 										content="Login to vote to skip songs"
-										v-tippy
+										v-tippy="{ theme: 'info' }"
 									>
 										<i
 											class="material-icons icon-with-button"
@@ -358,7 +358,7 @@
 										}}
 									</p>
 								</div>
-								<p id="volume-control">
+								<p id="volume-control" v-if="!isIOS">
 									<i
 										v-if="muted"
 										class="material-icons"
@@ -477,7 +477,7 @@
 											class="button is-success disabled"
 											id="like-song"
 											content="Login to like songs"
-											v-tippy
+											v-tippy="{ theme: 'info' }"
 										>
 											<i
 												class="material-icons icon-with-button"
@@ -490,7 +490,7 @@
 											class="button is-danger disabled"
 											id="dislike-song"
 											content="Login to dislike songs"
-											v-tippy
+											v-tippy="{ theme: 'info' }"
 										>
 											<i
 												class="material-icons icon-with-button"
@@ -504,7 +504,7 @@
 											<button
 												class="button is-primary disabled"
 												content="Login to add songs to playlist"
-												v-tippy
+												v-tippy="{ theme: 'info' }"
 											>
 												<i class="material-icons"
 													>queue</i
@@ -656,6 +656,7 @@ export default {
 	data() {
 		return {
 			utils,
+			isIOS: navigator.platform.match(/iPhone|iPod|iPad/),
 			title: "Station",
 			loading: true,
 			exists: true,
@@ -722,9 +723,8 @@ export default {
 				if (newValue === true) {
 					this.beforeEditSongModalLocalPaused = this.localPaused;
 					this.pauseLocalStation();
-				} else if (!this.beforeEditSongModalLocalPaused) {
+				} else if (!this.beforeEditSongModalLocalPaused)
 					this.resumeLocalStation();
-				}
 			}
 		);
 
@@ -1132,7 +1132,8 @@ export default {
 						iv_load_policy: 3,
 						rel: 0,
 						showinfo: 0,
-						disablekb: 1
+						disablekb: 1,
+						playsinline: 1
 					},
 					events: {
 						onReady: () => {
@@ -1150,6 +1151,14 @@ export default {
 							if (this.muted) this.player.mute();
 
 							this.playVideo();
+
+							// on ios, playback will be forcibly paused locally
+							if (this.isIOS) {
+								this.updateLocalPaused(true);
+								new Toast(
+									"Please click play manually to use Musare on iOS."
+								);
+							}
 						},
 						onError: err => {
 							console.log("error with youtube video", err);
@@ -1221,9 +1230,9 @@ export default {
 							} else if (
 								event.data === window.YT.PlayerState.PLAYING &&
 								this.seeking === true
-							) {
+							)
 								this.seeking = false;
-							}
+
 							if (
 								event.data === window.YT.PlayerState.PAUSED &&
 								!this.localPaused &&
@@ -1309,7 +1318,12 @@ export default {
 				}
 			}
 
-			if (!this.stationPaused && !this.localPaused && this.playerReady) {
+			if (
+				!this.stationPaused &&
+				!this.localPaused &&
+				this.playerReady &&
+				!this.isIOS
+			) {
 				const timeElapsed = this.getTimeElapsed();
 				const currentPlayerTime =
 					Math.max(
@@ -1319,7 +1333,6 @@ export default {
 					) * 1000;
 
 				const difference = timeElapsed - currentPlayerTime;
-				// console.log(difference);
 
 				let playbackRate = 1;
 

+ 3 - 1
frontend/src/store/modules/user.js

@@ -203,7 +203,8 @@ const modules = {
 		namespaced: true,
 		state: {
 			editing: "",
-			playlists: []
+			playlists: [],
+			fetchedPlaylists: false
 		},
 		actions: {
 			editPlaylist: ({ commit }, id) => commit("editPlaylist", id),
@@ -215,6 +216,7 @@ const modules = {
 				state.editing = id;
 			},
 			setPlaylists(state, playlists) {
+				state.fetchedPlaylists = true;
 				state.playlists = playlists;
 			}
 		}