Browse Source

refactor: change mechanism for how queue/playlist is reordered client-side to fix inconsistencies

Kristian Vos 2 months ago
parent
commit
ae0e5f920d

+ 8 - 6
backend/logic/actions/playlists.js

@@ -65,15 +65,15 @@ CacheModule.runJob("SUB", {
 });
 
 CacheModule.runJob("SUB", {
-	channel: "playlist.repositionSong",
+	channel: "playlist.changeOrder",
 	cb: res => {
-		const { createdBy, playlistId, song } = res;
+		const { createdBy, playlistId, playlistOrder } = res;
 
 		if (createdBy !== "Musare") {
 			WSModule.runJob("SOCKETS_FROM_USER", { userId: createdBy }, this).then(sockets =>
 				sockets.forEach(socket =>
-					socket.dispatch("event:playlist.song.repositioned", {
-						data: { playlistId, song }
+					socket.dispatch("event:playlist.order.changed", {
+						data: { playlistId, playlistOrder }
 					})
 				)
 			);
@@ -1138,12 +1138,14 @@ export default {
 					`Successfully repositioned song ${song.mediaSource} for private playlist "${playlistId}" for user "${session.userId}".`
 				);
 
+				const playlistOrder = playlist.songs.map(song => song.mediaSource);
+
 				CacheModule.runJob("PUB", {
-					channel: "playlist.repositionSong",
+					channel: "playlist.changeOrder",
 					value: {
 						createdBy: playlist.createdBy,
 						playlistId,
-						song
+						playlistOrder
 					}
 				});
 

+ 9 - 11
backend/logic/actions/stations.js

@@ -195,18 +195,18 @@ CacheModule.runJob("SUB", {
 });
 
 CacheModule.runJob("SUB", {
-	channel: "station.repositionSongInQueue",
+	channel: "station.changeQueueOrder",
 	cb: res => {
 		WSModule.runJob("EMIT_TO_ROOM", {
 			room: `station.${res.stationId}`,
-			args: ["event:station.queue.song.repositioned", { data: { song: res.song } }]
+			args: ["event:station.queue.order.changed", { data: { queueOrder: res.queueOrder } }]
 		});
 
 		WSModule.runJob("EMIT_TO_ROOM", {
 			room: `manage-station.${res.stationId}`,
 			args: [
-				"event:manageStation.queue.song.repositioned",
-				{ data: { stationId: res.stationId, song: res.song } }
+				"event:manageStation.queue.order.changed",
+				{ data: { stationId: res.stationId, queueOrder: res.queueOrder } }
 			]
 		});
 	}
@@ -2132,7 +2132,7 @@ export default {
 						.catch(next);
 				}
 			],
-			async err => {
+			async (err, station) => {
 				if (err) {
 					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
 					this.log(
@@ -2149,14 +2149,12 @@ export default {
 					`Repositioned song ${song.mediaSource} in queue of station "${stationId}" successfully.`
 				);
 
+				const queueOrder = station.queue.map(song => song.mediaSource);
+
 				CacheModule.runJob("PUB", {
-					channel: "station.repositionSongInQueue",
+					channel: "station.changeQueueOrder",
 					value: {
-						song: {
-							mediaSource: song.mediaSource,
-							oldIndex: song.oldIndex,
-							newIndex: song.newIndex
-						},
+						queueOrder,
 						stationId
 					}
 				});

+ 4 - 4
frontend/src/components/modals/EditPlaylist/index.vue

@@ -71,7 +71,7 @@ const {
 	addSong,
 	removeSong,
 	replaceSong,
-	repositionedSong
+	reorderSongsList,
 } = editPlaylistStore;
 
 const { closeCurrentModal, openModal } = useModalsStore();
@@ -320,13 +320,13 @@ onMounted(() => {
 	);
 
 	socket.on(
-		"event:playlist.song.repositioned",
+		"event:playlist.changeOrder",
 		res => {
 			if (playlist.value._id === res.data.playlistId) {
-				const { song, playlistId } = res.data;
+				const { playlistId, playlistOrder } = res.data;
 
 				if (playlist.value._id === playlistId) {
-					repositionedSong(song);
+					reorderSongsList(playlistOrder);
 				}
 			}
 		},

+ 3 - 3
frontend/src/components/modals/ManageStation/index.vue

@@ -64,7 +64,7 @@ const {
 	clearStation,
 	updateSongsList,
 	updateStationPlaylist,
-	repositionSongInList,
+	reorderSongsList,
 	updateStationPaused,
 	updateCurrentSong,
 	updateStation,
@@ -321,10 +321,10 @@ onMounted(() => {
 		);
 
 		socket.on(
-			"event:manageStation.queue.song.repositioned",
+			"event:manageStation.queue.order.changed",
 			res => {
 				if (res.data.stationId === stationId.value)
-					repositionSongInList(res.data.song);
+					reorderSongsList(res.data.queueOrder);
 			},
 			{ modalUuid: props.modalUuid }
 		);

+ 3 - 3
frontend/src/pages/Station/index.vue

@@ -238,7 +238,7 @@ const {
 	updateCurrentSong,
 	updateNextSong,
 	updateSongsList,
-	repositionSongInList,
+	reorderSongsList,
 	updateStationPaused,
 	updateLocalPaused,
 	updateNoSong,
@@ -1623,8 +1623,8 @@ onMounted(async () => {
 		autoRequestSong();
 	});
 
-	socket.on("event:station.queue.song.repositioned", res => {
-		repositionSongInList(res.data.song);
+	socket.on("event:station.queue.order.changed", res => {
+		reorderSongsList(res.data.queueOrder);
 
 		let nextSong = null;
 		if (songsList.value[0])

+ 12 - 13
frontend/src/stores/editPlaylist.ts

@@ -37,19 +37,18 @@ export const useEditPlaylistStore = ({ modalUuid }: { modalUuid: string }) =>
 			updatePlaylistSongs(playlistSongs) {
 				this.playlist.songs = playlistSongs;
 			},
-			repositionedSong(song) {
-				if (
-					this.playlist.songs[song.newIndex] &&
-					this.playlist.songs[song.newIndex].mediaSource ===
-						song.mediaSource
-				)
-					return;
-
-				this.playlist.songs.splice(
-					song.newIndex,
-					0,
-					this.playlist.songs.splice(song.oldIndex, 1)[0]
-				);
+			reorderSongsList(songsOrder) {
+				this.playlist.songs.sort((songA, songB) => {
+					const indexA = songsOrder.findIndex(
+						mediaSource => mediaSource === songA.mediaSource
+					);
+					const indexB = songsOrder.findIndex(
+						mediaSource => mediaSource === songB.mediaSource
+					);
+					if (indexA === indexB) return 0;
+					if (indexA > indexB) return 1;
+					if (indexA < indexB) return -1;
+				});
 			}
 		}
 	})();

+ 12 - 13
frontend/src/stores/manageStation.ts

@@ -64,19 +64,18 @@ export const useManageStationStore = ({ modalUuid }: { modalUuid: string }) =>
 			updateStationPlaylist(stationPlaylist) {
 				this.stationPlaylist = stationPlaylist;
 			},
-			repositionSongInList(song) {
-				if (
-					this.songsList[song.newIndex] &&
-					this.songsList[song.newIndex].mediaSource ===
-						song.mediaSource
-				)
-					return;
-
-				this.songsList.splice(
-					song.newIndex,
-					0,
-					this.songsList.splice(song.oldIndex, 1)[0]
-				);
+			reorderSongsList(songsOrder) {
+				this.songsList.sort((songA, songB) => {
+					const indexA = songsOrder.findIndex(
+						mediaSource => mediaSource === songA.mediaSource
+					);
+					const indexB = songsOrder.findIndex(
+						mediaSource => mediaSource === songB.mediaSource
+					);
+					if (indexA === indexB) return 0;
+					if (indexA > indexB) return 1;
+					if (indexA < indexB) return -1;
+				});
 			},
 			updateStationPaused(stationPaused) {
 				this.stationPaused = stationPaused;

+ 12 - 12
frontend/src/stores/station.ts

@@ -154,18 +154,18 @@ export const useStationStore = defineStore("station", {
 		updateSongsList(songsList) {
 			this.songsList = songsList;
 		},
-		repositionSongInList(song) {
-			if (
-				this.songsList[song.newIndex] &&
-				this.songsList[song.newIndex].mediaSource === song.mediaSource
-			)
-				return;
-
-			this.songsList.splice(
-				song.newIndex,
-				0,
-				this.songsList.splice(song.oldIndex, 1)[0]
-			);
+		reorderSongsList(songsOrder) {
+			this.songsList.sort((songA, songB) => {
+				const indexA = songsOrder.findIndex(
+					mediaSource => mediaSource === songA.mediaSource
+				);
+				const indexB = songsOrder.findIndex(
+					mediaSource => mediaSource === songB.mediaSource
+				);
+				if (indexA === indexB) return 0;
+				if (indexA > indexB) return 1;
+				if (indexA < indexB) return -1;
+			});
 		},
 		updateStationPaused(stationPaused) {
 			this.stationPaused = stationPaused;