Skip to content

Commit

Permalink
Also add reordering of your videos within the queue (swaps only betwe…
Browse files Browse the repository at this point in the history
…en videos of the same user)
  • Loading branch information
ysbrandB committed Sep 24, 2024
1 parent 24a20f3 commit 48662e5
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 16 deletions.
40 changes: 34 additions & 6 deletions client/src/components/CurrentQueue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@
</div>
</div>
<div
class="scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-proto_background_gray dark:scrollbar-thumb-neutral-800 dark:scrollbar-track-proto_background_gray-dark flex max-h-[84vh] justify-center overflow-y-scroll overscroll-contain px-0">
class="scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-proto_background_gray dark:scrollbar-thumb-neutral-800 dark:scrollbar-track-proto_background_gray-dark flex max-h-[84vh] justify-center overscroll-auto px-0">
<div v-if="skeletonLoading" class="w-full">
<ul class="grid gap-2">
<SkeletonResult v-for="index in 10" :key="index" />
</ul>
</div>
<div v-if="!skeletonLoading" class="w-full">
<ul class="grid gap-2 pr-4">
<TransitionGroup name="list" tag="ul" class="grid gap-2 pr-4">
<VideoCard
v-for="(video, index) in queue"
:key="video.id"
Expand All @@ -70,10 +70,15 @@
:channel="video.channel"
:duration="video.durationFormatted"
:thumbnail="video.thumbnail.url"
:removeButton="admin || video.user.id === userID"
:removeButton="props.admin || video.user.id === props.userID"
:canMoveUp="canMoveVideoUp(index)"
:canMoveDown="canMoveVideoDown(index)"
:videoID="video.id"
@remove-clicked="removeFromQueue([video.id])" />
</ul>
@remove-clicked="removeFromQueue([video.id])"
@move-clicked-up="moveVideo(video.id, true)"
@move-clicked-down="moveVideo(video.id, false)"
/>
</TransitionGroup>
<div
v-if="!skeletonLoading && queue.length < 1"
class="mt-4 text-gray-400">
Expand Down Expand Up @@ -113,6 +118,18 @@ const props = defineProps({
userID: Number,
});
const canMoveVideoDown = (videoIndex)=>{
return queue.value.slice(videoIndex, -1).some((video) => {
return (video.user.id === queue.value[videoIndex].user.id) && (props.admin || video.user.id === props.userID);
});
}
const canMoveVideoUp = (videoIndex)=>{
return queue.value.slice(0, videoIndex).some((video) => {
return (video.user.id === queue.value[videoIndex].user.id) && (props.admin || video.user.id === props.userID);
});
}
// return array of unique users in queue
const usersInQueue = computed(() => {
return queue.value.filter(
Expand All @@ -128,7 +145,6 @@ const userHasItemsInQueue = computed(() => {
const videosOfUser = queue.value.filter((video) => {
return video.user.id === props.userID;
});
console.log(videosOfUser);
return videosOfUser.length > 0;
});
Expand All @@ -151,6 +167,18 @@ async function removeFromQueue(videoIDs) {
});
}
async function moveVideo(videoID, up) {
const data = await new Promise((resolve) => {
normalSocket.emit("move-video", videoID, up, (callback) => {
resolve(callback);
});
});
emit("display-toast", {
status: data.status ?? enums.STATUS.SUCCESS,
message: data.message ?? `Successfully moved video` + (up ? " up!" : " down!"),
});
}
async function clearQueue() {
if (!props.admin) return;
const data = await new Promise((resolve) => {
Expand Down
43 changes: 36 additions & 7 deletions client/src/components/VideoCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,34 @@
class="absolute -right-0 -bottom-0 ml-auto mr-2 text-red-500">
</font-awesome-icon>

<button
v-if="removeButton"
class="absolute -right-0 -bottom-0 rounded-lg bg-red-600 py-2 px-3 text-xs font-medium text-white shadow-lg duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg"
@click="$emit('remove-clicked', videoID)">
<font-awesome-icon icon="fa-solid fa-trash" size="lg">
</font-awesome-icon>
</button>
<div class="absolute -right-0 -bottom-0 flex gap-1">
<button
v-if="canMoveUp"
class=" rounded-lg bg-proto_green py-2 px-3 text-xs font-medium text-white shadow-lg duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg"
@click="$emit('move-clicked-up', videoID)">
<font-awesome-icon
icon="fas fa-arrow-up"
fixed-width />
</button>

<button
v-if="canMoveDown"
class="rounded-lg bg-proto_green py-2 px-3 text-xs font-medium text-white shadow-lg duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg"
@click="$emit('move-clicked-down', videoID)">
<font-awesome-icon
icon="fa-solid fa-arrow-down"
fixed-width />

</button>

<button
v-if="removeButton"
class="rounded-lg bg-red-600 py-2 px-3 text-xs font-medium text-white shadow-lg duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg"
@click="$emit('remove-clicked', videoID)">
<font-awesome-icon icon="fa-solid fa-trash" size="lg">
</font-awesome-icon>
</button>
</div>
</ul>
</button>
</li>
Expand Down Expand Up @@ -154,6 +175,14 @@ const props = defineProps({
type: Boolean,
default: false,
},
canMoveUp: {
type: Boolean,
default: false,
},
canMoveDown: {
type: Boolean,
default: false,
},
textScrolling: {
type: Boolean,
default: false,
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/modals/PlaylistModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const addPlaylist = (shuffled) => {
{{ playlist.title }}
</div>

<img class="rounded-lg mb-1" :src="playlist.thumbnail.url" alt="album thumbnail"/>
<img class="rounded-lg mb-1 max-w-sm" :src="playlist.thumbnail.url" alt="album thumbnail"/>
<div class="mx-5 flex justify-between mb-3">
<div class="text-md text-gray-600 dark:text-white">
{{ playlist.channel }}
Expand Down
4 changes: 3 additions & 1 deletion client/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
faSearch,
faTrash,
faQuestionCircle,
faCaretDown,
faCaretDown, faArrowDown, faArrowUp
} from "@fortawesome/free-solid-svg-icons";

library.add(
Expand All @@ -44,6 +44,8 @@ library.add(
faSearch,
faTrash,
faCaretDown,
faArrowDown,
faArrowUp,
faQuestionCircle
);

Expand Down
37 changes: 37 additions & 0 deletions server/modules/QueueManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,43 @@ exports.moveToNext = () => {
return enums.SUCCESS;
};

exports.changeOrder = (videoID, up, userID, isAdmin = false) => {
// Find the video index in the queue
const index = queue.findIndex((video) => video.id == videoID);
// Video not found in the queue
if (index === -1) throw new softError("Video not found in the queue!");
// User is not an admin and does not own the video -> illegal move
if(!isAdmin && queue[index].user.id !== userID) throw new hardError("Illegal move of video!");
//find the index of the next video of this user if the video is moved up
if(!up){
//loop from the current index to the end of the queue and check if the user is the same
for(let i = index; i < queue.length; i++){
if(queue[i].user.id === queue[index].user.id && i !== index){
//swap the videos
let temp = queue[i];
queue[i] = queue[index];
queue[index] = temp;
eventBus.emit("queue-update");
return enums.SUCCESS;
}
}
}
if(up) {
//loop from the current index to the start of the queue and check if the user is the same
for(let i = index; i >= 0; i--){
if(queue[i].user.id === queue[index].user.id && i !== index){
//swap the videos
let temp = queue[i];
queue[i] = queue[index];
queue[index] = temp;
eventBus.emit("queue-update");
return enums.SUCCESS;
}
}
}
throw new softError("Could not find the video to swap with!");
}

// Removing videos by video id from the queue
exports.removeVideos = (videoIDs, userID, isAdmin = false) => {
let deletedVideos = 0;
Expand Down
18 changes: 18 additions & 0 deletions server/modules/socket_endpoints/RemoteSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,24 @@ endpoint.on("connection", (socket) => {
}
});

socket.on("move-video", (videoID, up, callback) => {
logger.clientInfo(
`${socket.id} Requested change in order ${up?'up':'down'} of ${videoID}`
);
try {
callback({
success: queueManager.changeOrder(
videoID,
up,
socket.request.session.passport.user.id,
socket.request.user.admin
),
});
} catch (e) {
callback(e.getInfo());
}
});

socket.on("get-queue", (callback) => {
callback({
queue: queueManager.getQueue(),
Expand Down
2 changes: 1 addition & 1 deletion server/utils/yt.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ exports.getPlaylistInfo = async(playlistId)=>{
return {
id: playlist.id,
title: playlist.title,
channel: playlist.channel.name,
channel: playlist.channel?.name,
thumbnail: playlist.thumbnails[playlist.thumbnails.length - 1],
videoCount: playlist.videoCount,
};
Expand Down

0 comments on commit 48662e5

Please sign in to comment.