Browse Source

feat: added initial support for SoundCloud info in ViewMedia modal

Kristian Vos 1 year ago
parent
commit
7afcb802d9

+ 21 - 1
backend/logic/actions/soundcloud.js

@@ -1,5 +1,6 @@
 import async from "async";
 
+import isLoginRequired from "../hooks/loginRequired";
 import { useHasPermission } from "../hooks/hasPermission";
 
 // eslint-disable-next-line
@@ -211,5 +212,24 @@ export default {
 				}
 			);
 		}
-	)
+	),
+
+	/**
+	 * Get a SoundCloud track
+	 *
+	 * @returns {{status: string, data: object}}
+	 */
+	getTrack: isLoginRequired(function getTrack(session, identifier, createMissing, cb) {
+		return SoundcloudModule.runJob("GET_TRACK", { identifier, createMissing }, this)
+			.then(res => {
+				this.log("SUCCESS", "SOUNDCLOUD_GET_VIDEO", `Fetching track was successful.`);
+
+				return cb({ status: "success", message: "Successfully fetched SoundCloud video", data: res.track });
+			})
+			.catch(async err => {
+				err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
+				this.log("ERROR", "SOUNDCLOUD_GET_VIDEO", `Fetching track failed. "${err}"`);
+				return cb({ status: "error", message: err });
+			});
+	})
 };

+ 143 - 0
frontend/src/components/SoundcloudTrackInfo.vue

@@ -0,0 +1,143 @@
+<script setup lang="ts">
+import { defineAsyncComponent } from "vue";
+
+import utils from "@/utils";
+
+export type SoundcloudTrack = {
+	_id: string;
+	trackId: string;
+	userPermalink: string;
+	permalink: string;
+	title: string;
+	username: string;
+	duration: number;
+	soundcloudCreatedAt: string;
+	artworkUrl: string;
+};
+
+const SongThumbnail = defineAsyncComponent(
+	() => import("@/components/SongThumbnail.vue")
+);
+
+defineProps<{
+	track: SoundcloudTrack;
+}>();
+</script>
+
+<template>
+	<div class="soundcloud-track-info-container">
+		<div class="left-section">
+			<p>
+				<strong>ID:</strong>
+				<span :title="track._id">{{ track._id }}</span>
+			</p>
+			<p>
+				<strong>SoundCloud ID:</strong>
+				<a
+					:href="`https://soundcloud.com/${track.userPermalink}/${track.permalink}`"
+					target="_blank"
+				>
+					{{ track.trackId }}
+				</a>
+			</p>
+			<p>
+				<strong>Title:</strong>
+				<span :title="track.title">{{ track.title }}</span>
+			</p>
+			<p>
+				<strong>Artist:</strong>
+				<span :title="track.username">{{ track.username }}</span>
+			</p>
+			<p>
+				<strong>Duration:</strong>
+				<span :title="`${track.duration}`">{{ track.duration }}</span>
+			</p>
+			<p>
+				<strong>Created Date:</strong>
+				<span
+					:title="
+						track.soundcloudCreatedAt
+							? new Date(track.soundcloudCreatedAt).toString()
+							: 'Unknown'
+					"
+					>{{
+						track.soundcloudCreatedAt
+							? utils.getDateFormatted(
+									new Date(track.soundcloudCreatedAt)
+							  )
+							: "Unknown"
+					}}</span
+				>
+			</p>
+		</div>
+		<div class="right-section">
+			<song-thumbnail
+				:song="{
+					mediaSource: `soundcloud:${track.trackId}`,
+					thumbnail: track.artworkUrl
+				}"
+				class="thumbnail-preview"
+			/>
+		</div>
+	</div>
+</template>
+
+<style lang="less" scoped>
+.night-mode {
+	.soundcloud-track-info-container {
+		background-color: var(--dark-grey-3) !important;
+		border: 0 !important;
+
+		.duration-canvas {
+			background-color: var(--dark-grey-2) !important;
+		}
+	}
+}
+
+.soundcloud-track-info-container {
+	display: flex;
+	margin: 0 auto;
+	padding: 10px;
+	border: 1px solid var(--light-grey-3);
+	border-radius: @border-radius;
+
+	.left-section {
+		display: flex;
+		flex-direction: column;
+		flex-grow: 1;
+
+		p {
+			text-overflow: ellipsis;
+			white-space: nowrap;
+			overflow: hidden;
+
+			&:first-child {
+				margin-top: auto;
+			}
+
+			&:last-child {
+				margin-bottom: auto;
+			}
+
+			& > span,
+			& > a {
+				margin-left: 5px;
+			}
+		}
+	}
+
+	:deep(.right-section .thumbnail-preview) {
+		width: 120px;
+		height: 120px;
+		margin: 0;
+	}
+
+	@media (max-width: 600px) {
+		flex-direction: column-reverse;
+
+		.left-section {
+			margin-top: 10px;
+		}
+	}
+}
+</style>

+ 41 - 1
frontend/src/components/modals/ViewMedia.vue

@@ -13,15 +13,19 @@ import { useUserAuthStore } from "@/stores/userAuth";
 
 import Modal from "@/components/Modal.vue";
 import { YoutubeVideo } from "@/components/YoutubeVideoInfo.vue";
+import { SoundcloudTrack } from "@/components/SoundcloudTrackInfo.vue";
 
 const YoutubeVideoInfo = defineAsyncComponent(
 	() => import("@/components/YoutubeVideoInfo.vue")
 );
-
 const YoutubePlayer = defineAsyncComponent(
 	() => import("@/components/YoutubePlayer.vue")
 );
 
+const SoundcloudTrackInfo = defineAsyncComponent(
+	() => import("@/components/SoundcloudTrackInfo.vue")
+);
+
 const props = defineProps({
 	modalUuid: { type: String, required: true },
 	mediaSource: { type: String, default: null }
@@ -35,6 +39,18 @@ const youtubeVideo = ref<YoutubeVideo>({
 	duration: 0
 });
 
+const soundcloudTrack = ref<SoundcloudTrack>({
+	_id: null,
+	trackId: null,
+	userPermalink: null,
+	permalink: null,
+	title: null,
+	username: null,
+	duration: 0,
+	soundcloudCreatedAt: null,
+	artworkUrl: null
+});
+
 const currentSongMediaType = computed(() => props.mediaSource.split(":")[0]);
 const currentSongMediaValue = computed(() => props.mediaSource.split(":")[1]);
 
@@ -109,6 +125,26 @@ onMounted(() => {
 				},
 				{ modalUuid: props.modalUuid }
 			);
+		} else if (currentSongMediaType.value === "soundcloud") {
+			socket.dispatch(
+				"soundcloud.getTrack",
+				currentSongMediaValue.value,
+				true,
+				res => {
+					if (res.status === "success") {
+						soundcloudTrack.value = res.data;
+						loaded.value = true;
+
+						socket.dispatch(
+							"apis.joinRoom",
+							`view-media.${props.mediaSource}`
+						);
+					} else {
+						new Toast("SoundCloud track with that ID not found");
+						closeCurrentModal();
+					}
+				}
+			);
 		}
 	});
 });
@@ -132,6 +168,10 @@ onBeforeUnmount(() => {
 					<youtube-video-info :video="youtubeVideo" />
 					<youtube-player :song="youtubeSongNormalized" />
 				</template>
+				<template v-else-if="currentSongMediaType === 'soundcloud'">
+					<soundcloud-track-info :track="soundcloudTrack" />
+					<!-- <youtube-player :song="youtubeSongNormalized" /> -->
+				</template>
 			</template>
 			<div v-else class="vertical-padding">
 				<p>Media hasn't loaded yet</p>