Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the option to shuffle playlists and swap the order of your songs. #139

Merged
merged 6 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
commonjs: true,
es2021: true,
},
extends: ["plugin:vue/vue3-essential", "eslint:recommended"],
extends: ["eslint:recommended", "plugin:vue/vue3-recommended", "prettier"],
overrides: [],
parserOptions: {
ecmaVersion: "latest",
Expand Down
46 changes: 40 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,14 @@
: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 +117,24 @@ 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 +150,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 +172,19 @@ 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
12 changes: 6 additions & 6 deletions client/src/components/HeaderFieldButtons.vue
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
<template>
<div
:class="classes"
class="display-block mr-6 ml-2 mt-auto shrink-0 justify-center">
class="display-block ml-2 mr-6 mt-auto shrink-0 justify-center">
<div v-if="name" class="my-2 text-2xl text-white">Welcome {{ name }}!</div>
<div
class="grid grid-cols-2 gap-2 sm:grid-cols-4 md:grid-cols-2 xl:grid-cols-4">
<router-link
to="/screen/admin"
v-if="adminScreen"
class="bg-proto_blue rounded-md py-2 px-4 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
class="bg-proto_blue rounded-md px-4 py-2 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
Admin screen
</router-link>
<router-link
to="/screen"
v-if="screen"
class="bg-proto_blue rounded-md py-2 px-4 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
class="bg-proto_blue rounded-md px-4 py-2 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
Screen
</router-link>
<router-link
to="/statistics"
v-if="statistics"
class="bg-proto_blue rounded-md py-2 px-4 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
class="bg-proto_blue rounded-md px-4 py-2 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
Statistics
</router-link>
<router-link
to="/remote"
v-if="remote"
class="bg-proto_blue rounded-md py-2 px-4 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
class="bg-proto_blue rounded-md px-4 py-2 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
Remote
</router-link>
<router-link
to="/soundboard"
v-if="soundboard"
class="bg-proto_blue rounded-md py-2 px-4 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
class="bg-proto_blue rounded-md px-4 py-2 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg">
Soundboard
</router-link>
</div>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/MasterControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
<div class="absolute -right-full min-w-max">
<button
@click="resetScreenCode"
class="bg-proto_blue hover:bg-proto_blue/80 rounded-md py-1 px-2 text-sm text-white shadow-md duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80">
class="bg-proto_blue hover:bg-proto_blue/80 rounded-md px-2 py-1 text-sm text-white shadow-md duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80">
New code
</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/PincodeComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ onMounted(() => {
});

socket.on("connect_error", (err) => {
if (err.message == "Invalid screencode")
if (err.message === "Invalid screencode")
processPinEntered(false, "Invalid pincode entered!");
processPinEntered(false, err);
// else processPinEntered(false, "Whoops.. Can't do anything with this response..");
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/RadioScreen.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
style="width: 150px"
:src="`https://www.nederland.fm/i/l/${radio.z}.gif`" />
<div
class="from-proto_blue absolute -top-1/2 -left-1/4 -z-10 h-52 w-52 animate-[spin_3s_linear_infinite] bg-gradient-to-r via-white to-white" />
class="from-proto_blue absolute -left-1/4 -top-1/2 -z-10 h-52 w-52 animate-[spin_3s_linear_infinite] bg-gradient-to-r via-white to-white" />
</div>
<br />
<audio
Expand All @@ -19,7 +19,7 @@
height="200"></audio>
<button
v-if="playButton"
class="bg-proto_blue hover:bg-proto_blue/80 my-auto mx-auto mt-5 flex rounded-md py-1 px-2 text-white shadow-md"
class="bg-proto_blue hover:bg-proto_blue/80 mx-auto my-auto mt-5 flex rounded-md px-2 py-1 text-white shadow-md"
@click="playClick">
play audio
</button>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/ResultsWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</ul>
<button
v-if="videos.length > 17"
class="bg-proto_blue mt-4 flex-none rounded-md py-2 px-4 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg"
class="bg-proto_blue mt-4 flex-none rounded-md px-4 py-2 text-center text-white duration-200 hover:-translate-x-1 hover:-translate-y-0.5 hover:opacity-80 hover:shadow-lg"
@click="$emit('nextPage')">
Get more results
</button>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/SearchWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

<div
@mouseleave="infoTooltipVisible = false"
class="absolute top-0 right-0 m-3 hidden md:block">
class="absolute right-0 top-0 m-3 hidden md:block">
<font-awesome-icon
@mouseenter="infoTooltipVisible = true"
icon="fa-solid fa-question-circle"
Expand All @@ -53,7 +53,7 @@
</font-awesome-icon>
<div
v-show="infoTooltipVisible"
class="dark:bg-proto_secondary_gray-dark transition-300 float-left mr-3 max-w-[250px] rounded-md bg-white py-2 px-5 text-justify dark:text-white">
class="dark:bg-proto_secondary_gray-dark transition-300 float-left mr-3 max-w-[250px] rounded-md bg-white px-5 py-2 text-justify dark:text-white">
If you are experiencing any problems with ProTube or have a feature
request please let the
<a
Expand Down
52 changes: 38 additions & 14 deletions client/src/components/VideoCard.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<transition @before-enter="beforeEnter" @enter="enter" appear>
<transition appear @before-enter="beforeEnter" @enter="enter">
<li
class="col-span-1 flex w-full flex-col overflow-hidden text-center shadow duration-200"
:class="roundedCorners ? 'rounded-lg' : 'rounded-sm'"
Expand All @@ -14,14 +14,14 @@
class="bg-proto_blue absolute bottom-0 h-2 w-0 rounded-sm opacity-60"></div>
<button
:disabled="!clickable"
@click="$emit('video-clicked', videoID)"
:class="[
clickable && statusIcon === enums.STATUS.NOTHING
? 'hover:bg-white/40 dark:hover:bg-stone-800/40'
: 'cursor-default',
{ 'rounded-lg': roundedCorners },
]"
class="border-proto_blue flex flex-1 flex-col border-l-4 bg-white/80 px-8 py-4 duration-200 dark:border-gray-800 dark:bg-stone-800/80">
class="border-proto_blue flex flex-1 flex-col border-l-4 bg-white/80 px-8 py-4 duration-200 dark:border-gray-800 dark:bg-stone-800/80"
@click="$emit('video-clicked', videoID)">
<div
class="text-md w-full overflow-x-hidden text-lg font-bold text-gray-800 dark:text-stone-300">
<h3
Expand All @@ -36,7 +36,7 @@
</h3>
</div>
<ul
class="fa-ul relative mt-auto ml-5 w-full text-right text-sm font-medium text-gray-900 dark:text-stone-300">
class="fa-ul relative ml-5 mt-auto w-full text-right text-sm font-medium text-gray-900 dark:text-stone-300">
<li
v-if="name"
class="justify-bottom mt-auto flex flex-1 align-bottom">
Expand Down Expand Up @@ -82,30 +82,46 @@
v-show="statusIcon === enums.STATUS.SUCCESS"
icon="fa-solid fa-check-circle"
size="lg"
class="absolute -right-0 -bottom-0 ml-auto mr-2 text-green-500">
class="absolute -bottom-0 -right-0 ml-auto mr-2 text-green-500">
</font-awesome-icon>

<font-awesome-icon
v-show="statusIcon === enums.STATUS.WARNING"
icon="fa-solid fa-warning"
size="lg"
class="absolute -right-0 -bottom-0 ml-auto mr-2 text-yellow-400">
class="absolute -bottom-0 -right-0 ml-auto mr-2 text-yellow-400">
</font-awesome-icon>

<font-awesome-icon
v-show="statusIcon === enums.STATUS.ERROR"
icon="fa-solid fa-xmark-circle"
size="lg"
class="absolute -right-0 -bottom-0 ml-auto mr-2 text-red-500">
class="absolute -bottom-0 -right-0 ml-auto mr-2 text-red-500">
</font-awesome-icon>

<button
v-if="removeButton"
@click="$emit('remove-clicked', videoID)"
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">
<font-awesome-icon icon="fa-solid fa-trash" size="lg">
</font-awesome-icon>
</button>
<div class="absolute -bottom-0 -right-0 flex gap-1">
<button
v-if="canMoveUp"
class="bg-proto_green rounded-lg px-3 py-2 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="bg-proto_green rounded-lg px-3 py-2 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 px-3 py-2 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 +170,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/LoadModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
role="dialog"
aria-modal="true">
<div
class="flex h-5/6 items-end justify-center px-4 pt-4 pb-20 text-center sm:block sm:p-0">
class="flex h-5/6 items-end justify-center px-4 pb-20 pt-4 text-center sm:block sm:p-0">
<div
class="bg-proto_background_gray-dark/50 fixed inset-0 transition-opacity"
aria-hidden="true"></div>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/modals/PincodeModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
role="dialog"
aria-modal="true">
<div
class="flex h-4/6 items-end justify-center px-4 pt-4 pb-20 text-center sm:block sm:p-0">
class="flex h-4/6 items-end justify-center px-4 pb-20 pt-4 text-center sm:block sm:p-0">
<div
class="fixed inset-0 bg-gray-600/75 transition-opacity dark:bg-gray-600/90"
aria-hidden="true"></div>
Expand All @@ -18,7 +18,7 @@
>

<div
class="dark:bg-proto_background_gray-dark my-auto inline-block w-full transform overflow-hidden rounded-md bg-white px-6 pt-5 pb-4 text-left align-bottom text-xl shadow-xl transition-all dark:text-gray-50 sm:my-8 sm:w-full sm:max-w-lg sm:p-6 sm:align-middle lg:w-8/12">
class="dark:bg-proto_background_gray-dark my-auto inline-block w-full transform overflow-hidden rounded-md bg-white px-6 pb-4 pt-5 text-left align-bottom text-xl shadow-xl transition-all dark:text-gray-50 sm:my-8 sm:w-full sm:max-w-lg sm:p-6 sm:align-middle lg:w-8/12">
Connect to the ProTube display
<div class="ml-1 pb-4 text-sm text-gray-400">
Enter the PIN on the ProTube screen
Expand Down
Loading