mirror of
https://github.com/JuLi0n21/pwa-player.git
synced 2026-04-19 15:30:05 +00:00
reformat, add data refresh button
This commit is contained in:
@@ -28,12 +28,11 @@ function highlightText(text: string, searchterm: string) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full h-full text-xs">
|
<div class="w-full h-full text-xs">
|
||||||
|
|
||||||
<div v-if="props.artist && props.artist.length > 0" class="mb-4">
|
<div v-if="props.artist && props.artist.length > 0" class="mb-4">
|
||||||
<h2 class="px-4 py-2 font-semibold text-lg uppercase tracking-wider action">Artists</h2>
|
<h2 class="px-4 py-2 font-semibold text-lg uppercase tracking-wider action">Artists</h2>
|
||||||
<ul class="space-y-1 px-2">
|
<ul class="space-y-1 px-2">
|
||||||
<li v-for="(artist, index) in props.artist" :key="index">
|
<li v-for="(artist, index) in props.artist" :key="index">
|
||||||
<RouterLink
|
<RouterLink
|
||||||
class="flex items-center bg-white/5 hover:bg-white/10 p-3 border border-transparent rounded-xl transition-colors hover:bordercolor"
|
class="flex items-center bg-white/5 hover:bg-white/10 p-3 border border-transparent rounded-xl transition-colors hover:bordercolor"
|
||||||
:to="'/search?a=' + artist"
|
:to="'/search?a=' + artist"
|
||||||
>
|
>
|
||||||
@@ -48,15 +47,18 @@ function highlightText(text: string, searchterm: string) {
|
|||||||
|
|
||||||
<div v-if="props.songs && props.songs.length > 0">
|
<div v-if="props.songs && props.songs.length > 0">
|
||||||
<h2 class="px-4 py-2 font-semibold text-lg uppercase tracking-wider action">Songs</h2>
|
<h2 class="px-4 py-2 font-semibold text-lg uppercase tracking-wider action">Songs</h2>
|
||||||
<ul class="space-y-1 px-2 pb-20"> <li v-for="(song, index) in props.songs" :key="index">
|
<ul class="space-y-1 px-2 pb-20">
|
||||||
<button
|
<li v-for="(song, index) in props.songs" :key="index">
|
||||||
@click="playSong(song.hash)"
|
<button
|
||||||
|
@click="playSong(song.hash)"
|
||||||
class="flex items-center p-2 rounded-xl w-full text-left transition-colors"
|
class="flex items-center p-2 rounded-xl w-full text-left transition-colors"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="song.previewimage
|
:src="
|
||||||
? `${userStore.cloudflareUrl.value}${song.previewimage}?h=120&w=120`
|
song.previewimage
|
||||||
: '/default-bg.png'"
|
? `${userStore.cloudflareUrl.value}${song.previewimage}?h=120&w=120`
|
||||||
|
: '/default-bg.png'
|
||||||
|
"
|
||||||
class="rounded-lg w-12 h-12 object-cover shrink-0"
|
class="rounded-lg w-12 h-12 object-cover shrink-0"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
@@ -80,4 +82,4 @@ function highlightText(text: string, searchterm: string) {
|
|||||||
:deep(.text-yellow-400) {
|
:deep(.text-yellow-400) {
|
||||||
color: #facc15;
|
color: #facc15;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full h-full text-xs animate-pulse">
|
<div class="w-full h-full text-xs animate-pulse">
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<div class="my-2 ml-4 rounded w-24 h-6 action"></div>
|
<div class="my-2 ml-4 rounded w-24 h-6 action"></div>
|
||||||
<ul class="space-y-1 px-2">
|
<ul class="space-y-1 px-2">
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
<li v-for="i in 6" :key="'song-skel-' + i">
|
<li v-for="i in 6" :key="'song-skel-' + i">
|
||||||
<div class="flex items-center p-2 rounded-xl w-full">
|
<div class="flex items-center p-2 rounded-xl w-full">
|
||||||
<div class="rounded-lg w-12 h-12 shrink-0"></div>
|
<div class="rounded-lg w-12 h-12 shrink-0"></div>
|
||||||
|
|
||||||
<div class="flex-1 space-y-2 ml-3">
|
<div class="flex-1 space-y-2 ml-3">
|
||||||
<div class="rounded w-3/4 h-4 info"></div>
|
<div class="rounded w-3/4 h-4 info"></div>
|
||||||
<div class="rounded w-1/2 h-3 b action"></div>
|
<div class="rounded w-1/2 h-3 b action"></div>
|
||||||
@@ -28,7 +27,6 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -38,10 +36,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% { opacity: 1; }
|
0%,
|
||||||
50% { opacity: 0.4; }
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.info { background-color: currentColor; opacity: 0.1; }
|
.info {
|
||||||
.action { background-color: currentColor; opacity: 0.05; }
|
background-color: currentColor;
|
||||||
</style>
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
.action {
|
||||||
|
background-color: currentColor;
|
||||||
|
opacity: 0.05;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -85,12 +85,14 @@ onBeforeUnmount(() => {
|
|||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="gap-2 grid grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 p-2 overflow-y-auto collection-container song-item-wrapper coll-container">
|
<div
|
||||||
|
class="gap-2 grid grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 p-2 overflow-y-auto collection-container song-item-wrapper coll-container"
|
||||||
|
>
|
||||||
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
||||||
|
|
||||||
<template v-if="loading">
|
<template v-if="loading">
|
||||||
<SongItemSkeleton v-for="i in 10" :key="'skeleton-' + i" />
|
<SongItemSkeleton v-for="i in 10" :key="'skeleton-' + i" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
@@ -98,7 +100,7 @@ onBeforeUnmount(() => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.song-item-wrapper {
|
.song-item-wrapper {
|
||||||
content-visibility: auto;
|
content-visibility: auto;
|
||||||
|
|
||||||
contain-intrinsic-size: 96px;
|
contain-intrinsic-size: 96px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ const props = defineProps<{ collection: CollectionPreview }>();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<RouterLink :to="'/collection/' + props.collection.index" class="w-full">
|
<RouterLink :to="'/collection/' + props.collection.index" class="w-full">
|
||||||
<div class="flex items-center border rounded-lg h-24 overflow-hidden bordercolor"> <img
|
<div class="flex items-center border rounded-lg h-24 overflow-hidden bordercolor">
|
||||||
|
<img
|
||||||
class="p-1 rounded-lg w-24 h-24"
|
class="p-1 rounded-lg w-24 h-24"
|
||||||
:src="encodeURI(`${userStore.cloudflareUrl.value}${props.collection.previewimage}`)"
|
:src="encodeURI(`${userStore.cloudflareUrl.value}${props.collection.previewimage}`)"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-col overflow-hidden text-left">
|
<div class="flex flex-col overflow-hidden text-left">
|
||||||
<h3 class="overflow-hidden text-ellipsis whitespace-nowrap info">{{ props.collection.name }}</h3>
|
<h3 class="overflow-hidden text-ellipsis whitespace-nowrap info">{{ props.collection.name }}</h3>
|
||||||
<h5 class="text-sm info">{{ props.collection.length }} Songs</h5>
|
<h5 class="text-sm info">{{ props.collection.length }} Songs</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,19 +18,21 @@ function updateSong() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
@click="updateSong"
|
@click="updateSong"
|
||||||
:style="{ borderColor: border }"
|
:style="{ borderColor: border }"
|
||||||
class="flex items-center m-1 border rounded-lg h-16 md:h-24 overflow-hidden md:text-xl cursor-pointer bordercolor"
|
class="flex items-center m-1 border rounded-lg h-16 md:h-24 overflow-hidden md:text-xl cursor-pointer bordercolor"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="p-1 rounded-lg w-14 md:w-24 h-16 md:h-24 object-cover shrink-0"
|
class="p-1 rounded-lg w-14 md:w-24 h-16 md:h-24 object-cover shrink-0"
|
||||||
:src="props.song?.previewimage
|
:src="
|
||||||
? encodeURI(`${userStore.cloudflareUrl.value}${props.song.previewimage}?h=56&w=56`)
|
props.song?.previewimage
|
||||||
: '/default-bg.png'"
|
? encodeURI(`${userStore.cloudflareUrl.value}${props.song.previewimage}?h=56&w=56`)
|
||||||
|
: '/default-bg.png'
|
||||||
|
"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-col flex-1 justify-center overflow-hidden text-left">
|
<div class="flex flex-col flex-1 justify-center overflow-hidden text-left">
|
||||||
<p :style="{ color: info }" class="overflow-hidden text-base text-ellipsis text-nowrap info">
|
<p :style="{ color: info }" class="overflow-hidden text-base text-ellipsis text-nowrap info">
|
||||||
<slot name="songName">{{ props.song?.name || "Unknown Title" }}</slot>
|
<slot name="songName">{{ props.song?.name || "Unknown Title" }}</slot>
|
||||||
@@ -49,4 +51,4 @@ function updateSong() {
|
|||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ const fetchCollections = async () => {
|
|||||||
const container = containerRef.value;
|
const container = containerRef.value;
|
||||||
if (container) {
|
if (container) {
|
||||||
const noScrollbarYet = container.scrollHeight <= container.clientHeight + 0;
|
const noScrollbarYet = container.scrollHeight <= container.clientHeight + 0;
|
||||||
|
|
||||||
const mightBeMoreData = newItems.length === limit.value;
|
const mightBeMoreData = newItems.length === limit.value;
|
||||||
|
|
||||||
if (noScrollbarYet && mightBeMoreData) {
|
if (noScrollbarYet && mightBeMoreData) {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
return await fetchCollections();
|
return await fetchCollections();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,17 +66,12 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="flex flex-col w-full h-full overflow-hidden">
|
<main class="flex flex-col w-full h-full overflow-hidden">
|
||||||
|
<div
|
||||||
<div
|
ref="containerRef"
|
||||||
ref="containerRef"
|
|
||||||
class="flex-1 content-start gap-2 grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 p-2 overflow-y-auto"
|
class="flex-1 content-start gap-2 grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 p-2 overflow-y-auto"
|
||||||
style="min-height: 0;"
|
style="min-height: 0"
|
||||||
>
|
>
|
||||||
<CollectionListItem
|
<CollectionListItem v-for="(collection, index) in collections" :key="index" :collection="collection" />
|
||||||
v-for="(collection, index) in collections"
|
|
||||||
:key="index"
|
|
||||||
:collection="collection"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<template v-if="isLoading">
|
<template v-if="isLoading">
|
||||||
<CollectionListItemSkeleton v-for="i in 12" :key="'skeleton-' + i" />
|
<CollectionListItemSkeleton v-for="i in 12" :key="'skeleton-' + i" />
|
||||||
@@ -96,4 +91,4 @@ onMounted(async () => {
|
|||||||
content-visibility: auto;
|
content-visibility: auto;
|
||||||
contain-intrinsic-size: 96px;
|
contain-intrinsic-size: 96px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -107,36 +107,40 @@ function reset() {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="flex flex-col flex-1 h-full overflow-y-scroll">
|
<main class="flex flex-col flex-1 h-full overflow-y-scroll">
|
||||||
<div class="flex flex-col gap-2 p-4">
|
<div class="flex flex-col gap-2 p-4">
|
||||||
<div class="flex gap-1 overflow-hidden">
|
<div class="flex gap-1 overflow-hidden">
|
||||||
<input
|
<input
|
||||||
@change="update"
|
@change="update"
|
||||||
type="text"
|
type="text"
|
||||||
id="url-input"
|
id="url-input"
|
||||||
:value="userStore.cloudflareUrl.value"
|
:value="userStore.cloudflareUrl.value"
|
||||||
class="flex-1 bg-white/5 p-2 border-y border-l rounded-l-lg outline-none bordercolor"
|
class="flex-1 bg-white/5 p-2 border-y border-l rounded-l-lg outline-none bordercolor"
|
||||||
placeholder="https://..."
|
placeholder="https://..."
|
||||||
/>
|
/>
|
||||||
<button @click="copyToClipboard" class="bg-white/5 hover:bg-white/10 p-2 border bordercolor" title="Copy URL">
|
<button @click="copyToClipboard" class="bg-white/5 hover:bg-white/10 p-2 border bordercolor" title="Copy URL">
|
||||||
<i class="fa-solid fa-copy"></i>
|
<i class="fa-solid fa-copy"></i>
|
||||||
</button>
|
</button>
|
||||||
<button @click="pasteFromClipboard" class="bg-white/5 hover:bg-white/10 p-2 border rounded-r-lg text-yellow-500 bordercolor" title="Paste URL">
|
<button
|
||||||
|
@click="pasteFromClipboard"
|
||||||
|
class="bg-white/5 hover:bg-white/10 p-2 border rounded-r-lg text-yellow-500 bordercolor"
|
||||||
|
title="Paste URL"
|
||||||
|
>
|
||||||
<i class="fa-solid fa-paste"></i>
|
<i class="fa-solid fa-paste"></i>
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
v-if="isHealthy !== null"
|
v-if="isHealthy !== null"
|
||||||
class="self-center rounded-full w-2 h-2"
|
class="self-center rounded-full w-2 h-2"
|
||||||
:class="isHealthy ? 'bg-green-500 shadow-[0_0_8px_green]' : 'bg-red-500 shadow-[0_0_8px_red]'"
|
:class="isHealthy ? 'bg-green-500 shadow-[0_0_8px_green]' : 'bg-red-500 shadow-[0_0_8px_red]'"
|
||||||
>
|
></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<button v-if="!userStore.user.value" @click="getMe" class="mx-4 p-0.5 border rounded-lg bordercolor">
|
<button v-if="!userStore.user.value" @click="getMe" class="mx-4 p-0.5 border rounded-lg bordercolor">
|
||||||
{{ loginStatus }}
|
{{ loginStatus }}
|
||||||
</button>
|
</button>
|
||||||
|
<button v-else @click="getMe" class="mx-4 p-0.5 border rounded-lg bordercolor">Refresh</button>
|
||||||
|
|
||||||
<div class="flex flex-col justify-around p-10 w-full">
|
<div class="flex flex-col justify-around p-10 w-full">
|
||||||
<div class="flex flex-1 justify-between">
|
<div class="flex flex-1 justify-between">
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ onMounted(async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="containerRef"
|
ref="containerRef"
|
||||||
class="flex-1 content-start gap-2 grid grid-cols-1 md:grid-cols-3 xl:grid-cols-4 p-1 overflow-y-scroll coll-container"
|
class="flex-1 content-start gap-2 grid grid-cols-1 md:grid-cols-3 xl:grid-cols-4 p-1 overflow-y-scroll coll-container"
|
||||||
>
|
>
|
||||||
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
||||||
@@ -79,4 +79,4 @@ onMounted(async () => {
|
|||||||
content-visibility: auto;
|
content-visibility: auto;
|
||||||
contain-intrinsic-size: 96px;
|
contain-intrinsic-size: 96px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ const showSearch = ref(false);
|
|||||||
|
|
||||||
async function fetchActiveSearch(term: string) {
|
async function fetchActiveSearch(term: string) {
|
||||||
if (!term.trim()) return emptySearch();
|
if (!term.trim()) return emptySearch();
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const response = await api.musicBackendSearch(term);
|
const response = await api.musicBackendSearch(term);
|
||||||
const songData = mapApiToSongs(response.data.songs ?? []);
|
const songData = mapApiToSongs(response.data.songs ?? []);
|
||||||
|
|
||||||
activesongs.value = songData;
|
activesongs.value = songData;
|
||||||
artists.value = response.data.artist ? [response.data.artist] : [];
|
artists.value = response.data.artist ? [response.data.artist] : [];
|
||||||
|
|
||||||
audioStore.setCollection(songData);
|
audioStore.setCollection(songData);
|
||||||
showSearch.value = true;
|
showSearch.value = true;
|
||||||
router.replace({ query: { ...route.query, s: term } });
|
router.replace({ query: { ...route.query, s: term } });
|
||||||
@@ -52,7 +52,7 @@ async function fetchActiveSearch(term: string) {
|
|||||||
async function fetchSearchArtist(artist: string) {
|
async function fetchSearchArtist(artist: string) {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
showSearch.value = false; // Hide recommendations overlay when a choice is made
|
showSearch.value = false; // Hide recommendations overlay when a choice is made
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await api.musicBackendArtist(artist);
|
const response = await api.musicBackendArtist(artist);
|
||||||
const data = mapApiToSongs(response.data.songs || []);
|
const data = mapApiToSongs(response.data.songs || []);
|
||||||
@@ -60,9 +60,9 @@ async function fetchSearchArtist(artist: string) {
|
|||||||
songs.value = data.map((song: Song) => ({
|
songs.value = data.map((song: Song) => ({
|
||||||
...song,
|
...song,
|
||||||
previewimage: `${userStore.cloudflareUrl.value}/api/v1/images/${song.previewimage}`,
|
previewimage: `${userStore.cloudflareUrl.value}/api/v1/images/${song.previewimage}`,
|
||||||
url: `${userStore.cloudflareUrl.value}/api/v1/audio/${song.url}`
|
url: `${userStore.cloudflareUrl.value}/api/v1/audio/${song.url}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
router.replace({ query: { ...route.query, a: artist } });
|
router.replace({ query: { ...route.query, a: artist } });
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
@@ -88,9 +88,12 @@ watch(searchInput, (val) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(() => route.query.a, (newArtist) => {
|
watch(
|
||||||
if (newArtist) fetchSearchArtist(newArtist as string);
|
() => route.query.a,
|
||||||
});
|
(newArtist) => {
|
||||||
|
if (newArtist) fetchSearchArtist(newArtist as string);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (route.query.a) fetchSearchArtist(route.query.a as string);
|
if (route.query.a) fetchSearchArtist(route.query.a as string);
|
||||||
@@ -118,9 +121,9 @@ onMounted(() => {
|
|||||||
placeholder="Type to Search..."
|
placeholder="Type to Search..."
|
||||||
class="flex-1 bg-white/5 p-4 border rounded-xl outline-none ring-yellow-500/50 focus:ring-2 w-full h-14 transition-all bordercolor"
|
class="flex-1 bg-white/5 p-4 border rounded-xl outline-none ring-yellow-500/50 focus:ring-2 w-full h-14 transition-all bordercolor"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="searchInput"
|
v-if="searchInput"
|
||||||
class="top-1/2 right-6 absolute opacity-50 hover:opacity-100 -translate-y-1/2 cursor-pointer"
|
class="top-1/2 right-6 absolute opacity-50 hover:opacity-100 -translate-y-1/2 cursor-pointer"
|
||||||
@click="emptySearch"
|
@click="emptySearch"
|
||||||
>
|
>
|
||||||
<i class="text-xl far fa-times-circle"></i>
|
<i class="text-xl far fa-times-circle"></i>
|
||||||
@@ -128,35 +131,24 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative flex-1 overflow-y-auto">
|
<div class="relative flex-1 overflow-y-auto">
|
||||||
|
<div
|
||||||
<div
|
v-if="showSearch && (activesongs.length || artists.length || isLoading)"
|
||||||
v-if="showSearch && (activesongs.length || artists.length || isLoading)"
|
|
||||||
class="z-20 absolute backdrop-blur-xl w-full min-h-full"
|
class="z-20 absolute backdrop-blur-xl w-full min-h-full"
|
||||||
>
|
>
|
||||||
<ActiveSearchSkeleton v-if="isLoading" />
|
<ActiveSearchSkeleton v-if="isLoading" />
|
||||||
|
|
||||||
<ActiveSearchList
|
<ActiveSearchList v-else :songs="activesongs" :artist="artists" :search="searchInput" />
|
||||||
v-else
|
|
||||||
:songs="activesongs"
|
|
||||||
:artist="artists"
|
|
||||||
:search="searchInput"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<SongItem
|
<SongItem v-for="(song, index) in songs" :key="song.hash || index" :song="song" class="song-render-node" />
|
||||||
v-for="(song, index) in songs"
|
</template>
|
||||||
:key="song.hash || index"
|
|
||||||
:song="song"
|
<div v-if="!isLoading && songs.length === 0 && !showSearch" class="col-span-full opacity-30 py-20 text-center">
|
||||||
class="song-render-node"
|
<i class="mb-4 text-6xl fa-solid fa-music"></i>
|
||||||
/>
|
<p>Find your favorite music</p>
|
||||||
</template>
|
|
||||||
|
|
||||||
<div v-if="!isLoading && songs.length === 0 && !showSearch" class="col-span-full opacity-30 py-20 text-center">
|
|
||||||
<i class="mb-4 text-6xl fa-solid fa-music"></i>
|
|
||||||
<p>Find your favorite music</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -165,4 +157,4 @@ onMounted(() => {
|
|||||||
content-visibility: auto;
|
content-visibility: auto;
|
||||||
contain-intrinsic-size: 96px;
|
contain-intrinsic-size: 96px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user