mirror of
https://github.com/JuLi0n21/pwa-player.git
synced 2026-04-19 23:40:05 +00:00
search feature
This commit is contained in:
@@ -7,20 +7,47 @@ import CollectionListItem from '../components/CollectionListItem.vue'
|
||||
const userStore = useUserStore();
|
||||
|
||||
const collections = ref<CollectionPreview[]>([]);
|
||||
const limit = ref(10);
|
||||
const offset = ref(0);
|
||||
const isLoading = ref(false);
|
||||
|
||||
onMounted(async () => {
|
||||
const data = await userStore.fetchCollections();
|
||||
const fetchCollections = async () => {
|
||||
if (isLoading.value) return;
|
||||
isLoading.value = true;
|
||||
|
||||
const data = await userStore.fetchCollections(offset.value, limit.value);
|
||||
data.forEach(song => {
|
||||
song.previewimage = `${userStore.baseUrl}api/v1/images/${song.previewimage}?h=80&w=80`;
|
||||
})
|
||||
collections.value = data;
|
||||
});
|
||||
|
||||
collections.value = [...collections.value, ...data];
|
||||
offset.value += limit.value;
|
||||
|
||||
isLoading.value = false;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchCollections();
|
||||
|
||||
const container = document.querySelector('.collection-container');
|
||||
if (container) {
|
||||
container.addEventListener('scroll', async () => {
|
||||
const scrollTop = container.scrollTop;
|
||||
const scrollHeight = container.scrollHeight;
|
||||
const clientHeight = container.clientHeight;
|
||||
|
||||
if (scrollTop + clientHeight >= scrollHeight * 0.9 && !isLoading.value) {
|
||||
await fetchCollections();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="flex-1 text-center flex flex-col h-full overflow-scroll">
|
||||
<div class="flex flex-col overflow-scroll">
|
||||
<div class="flex flex-col overflow-scroll collection-container">
|
||||
<CollectionListItem v-for="(collection, index) in collections" :key="index" :collection="collection" />
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -49,7 +49,7 @@ const audioStore = useAudioStore();
|
||||
<div class="flex flex-col justify-between mb-4">
|
||||
<i @click="audioStore.toggleRepeat" :class="[audioStore.repeat ? 'text-pink-500' : '']"
|
||||
class="fa-solid fa-repeat"></i>
|
||||
<i @click="this.$router.go(-1);" class="fa-solid fa-arrow-down"></i>
|
||||
<i @click="$router.go(-1);" class="fa-solid fa-arrow-down"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
|
||||
@@ -1,10 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
import SongItem from '../components/SongItem.vue'
|
||||
|
||||
import type { Song, CollectionPreview } from '../script/types'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
import { useRoute } from 'vue-router';
|
||||
import CollectionListItem from '../components/CollectionListItem.vue'
|
||||
import { useAudioStore } from '@/stores/audioStore';
|
||||
|
||||
const route = useRoute();
|
||||
const userStore = useUserStore();
|
||||
const audioStore = useAudioStore();
|
||||
|
||||
const songs = ref<Song[]>([]);
|
||||
const name = ref('name');
|
||||
|
||||
const limit = ref(100);
|
||||
const offset = ref(0);
|
||||
const isLoading = ref(false);
|
||||
|
||||
const fetchRecent = async () => {
|
||||
if (isLoading.value) return;
|
||||
|
||||
isLoading.value = true;
|
||||
const data = await userStore.fetchRecent(limit.value, offset.value);
|
||||
|
||||
data.forEach(song => {
|
||||
song.previewimage = `${userStore.baseUrl}api/v1/images/${song.previewimage}`;
|
||||
song.url = `${userStore.baseUrl}api/v1/audio/${song.url}`;
|
||||
});
|
||||
|
||||
offset.value += limit.value;
|
||||
console.log(data)
|
||||
songs.value = [...songs.value, ...data];
|
||||
|
||||
isLoading.value = false;
|
||||
audioStore.setCollection(null);
|
||||
}
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchRecent();
|
||||
|
||||
const container = document.querySelector('.song-container');
|
||||
if (container) {
|
||||
container.addEventListener('scroll', async () => {
|
||||
const scrollTop = container.scrollTop;
|
||||
const scrollHeight = container.scrollHeight;
|
||||
const clientHeight = container.clientHeight;
|
||||
|
||||
if (scrollTop + clientHeight >= scrollHeight * 0.9 && !isLoading.value) {
|
||||
await fetchRecent();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<main class="flex-1 flex-col overflow-scroll">
|
||||
<div class="flex-1 flex-col h-full overflow-scroll song-container">
|
||||
|
||||
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,81 @@
|
||||
<script setup lang="ts">
|
||||
import type { Song, CollectionPreview } from '../script/types'
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import ActiveSearchList from '../components/ActiveSearchList.vue'
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import SongItem from '../components/SongItem.vue'
|
||||
import { useAudioStore } from '@/stores/audioStore';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const audioStore = useAudioStore();
|
||||
const userStore = useUserStore();
|
||||
const activesongs = ref<Song[]>([]);
|
||||
const songs = ref<Song[]>([]);
|
||||
const artists = ref<string[]>([]);
|
||||
const showSearch = ref(false);
|
||||
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
await loadartistifexist();
|
||||
|
||||
const container = document.querySelector('.search') as HTMLInputElement;
|
||||
|
||||
if (container) {
|
||||
container.addEventListener('input', async (event: Event) => {
|
||||
showSearch.value = true;
|
||||
|
||||
const target = event.target as HTMLInputElement;
|
||||
if(target.value != undefined && target.value != ""){
|
||||
const data = await userStore.fetchActiveSearch(target.value)
|
||||
router.push({ query: {s: target.value } });
|
||||
|
||||
data.songs.forEach(song => {
|
||||
song.previewimage = `${userStore.baseUrl}api/v1/images/${song.previewimage}`;
|
||||
song.url = `${userStore.baseUrl}api/v1/audio/${song.url}`;
|
||||
});
|
||||
|
||||
activesongs.value = data.songs;
|
||||
audioStore.setCollection(data.songs)
|
||||
artists.value = data.artist;
|
||||
} else {
|
||||
activesongs.value = [];
|
||||
artists.value = [];
|
||||
showSearch.value = false;
|
||||
|
||||
}
|
||||
}
|
||||
)}
|
||||
const s = route.query.s as string;
|
||||
if(s){container.value = s; container.dispatchEvent(new Event('input'))}
|
||||
});
|
||||
|
||||
async function loadartistifexist(){
|
||||
const query = route.query.a as string;
|
||||
if (query) {
|
||||
showSearch.value = false;
|
||||
|
||||
const data = await userStore.fetchSearchArtist(query)
|
||||
console.log(data);
|
||||
|
||||
data.forEach(song => {
|
||||
song.previewimage = `${userStore.baseUrl}api/v1/images/${song.previewimage}`;
|
||||
song.url = `${userStore.baseUrl}api/v1/audio/${song.url}`;
|
||||
});
|
||||
|
||||
songs.value = data;
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => route.query.a, async (newQuery) => {
|
||||
|
||||
await loadartistifexist();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -12,8 +89,13 @@
|
||||
<hr>
|
||||
</div>
|
||||
</header>
|
||||
<main class="flex-1 flex-col">
|
||||
<h1> Search...</h1>
|
||||
<input class="flex-1 border border-pink-500 accent-pink-800 bg-yellow-300 bg-opacity-20 rounded-lg m-2 p-2" />
|
||||
<main class="flex flex-col flex-1 flex-col w-full h-full overflow-scroll">
|
||||
<input placeholder="Type to Search..." class="flex-1 max-h-12 search border border-pink-500 accent-pink-800 bg-yellow-300 bg-opacity-20 rounded-lg m-2 p-2" />
|
||||
<div class="relative flex flex-col w-full h-full overflow-scroll">
|
||||
<div v-if="showSearch" class="absolute w-full text-center search-recommendations z -20">
|
||||
<ActiveSearchList :songs="activesongs" :artist="artists"/>
|
||||
</div>
|
||||
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user