mirror of
https://github.com/JuLi0n21/pwa-player.git
synced 2026-04-19 23:40:05 +00:00
swap to generated api code and composables
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { Song, CollectionPreview } from '../script/types'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
import CollectionListItem from '../components/CollectionListItem.vue'
|
||||
import { useUser } from '@/composables/useUser';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const userStore = useUser();
|
||||
|
||||
const collections = ref<CollectionPreview[]>([]);
|
||||
const limit = ref(10);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
import SongItem from '../components/SongItem.vue'
|
||||
import { useAudioStore } from '@/stores/audioStore';
|
||||
import { useAudio } from '@/composables/useAudio';
|
||||
import { useUser } from '@/composables/useUser';
|
||||
import type { Me } from '@/script/types';
|
||||
|
||||
const audioStore = useAudioStore();
|
||||
const userStore = useUserStore();
|
||||
const audioStore = useAudio();
|
||||
const userStore = useUser();
|
||||
|
||||
const bgColor = ref('');
|
||||
const actionColor = ref('');
|
||||
@@ -16,7 +17,7 @@ const loginStatus = ref('Login');
|
||||
|
||||
function update() {
|
||||
var input = document.getElementById("url-input") as HTMLInputElement;
|
||||
userStore.baseUrl = input.value;
|
||||
userStore.baseUrl.value = input.value;
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +51,7 @@ async function getMe() {
|
||||
|
||||
console.log("active user: ", data.name)
|
||||
userStore.setUser(data);
|
||||
userStore.setBaseUrl(data.endpoint);
|
||||
userStore.baseUrl.value(data.endpoint);
|
||||
|
||||
}
|
||||
|
||||
@@ -87,15 +88,15 @@ function reset() {
|
||||
|
||||
<main class="flex-1 flex flex-col overflow-scroll">
|
||||
<h1> Meeeeee </h1>
|
||||
<input @change="update" type="text" id="url-input" :value="userStore.baseUrl" disabled />
|
||||
<input @change="update" type="text" id="url-input" :value="userStore.baseUrl.value" disabled />
|
||||
<br>
|
||||
<button v-if="!userStore.User" @click="getMe" class="border bordercolor rounded-lg p-0.5">{{ loginStatus }}</button>
|
||||
<div v-if="userStore.User" class="flex p-5 justify-between">
|
||||
<img :src="userStore.User.avatar_url" class="w-1/3">
|
||||
<button v-if="!userStore.user.value" @click="getMe" class="border bordercolor rounded-lg p-0.5">{{ loginStatus }}</button>
|
||||
<div v-if="userStore.user.value" class="flex p-5 justify-between">
|
||||
<img :src="userStore.user.value.avatar_url" class="w-1/3">
|
||||
<div>
|
||||
<p>{{ userStore.User.name }}</p>
|
||||
<p>{{ userStore.User.endpoint == "" ? 'Not Connected' : 'Connected' }}</p>
|
||||
<p>Sharing: <button @click="share" class="border bordercolor rounded-lg p-0.5">{{ userStore.User.share
|
||||
<p>{{ userStore.user.value.name }}</p>
|
||||
<p>{{ userStore.user.value.endpoint == "" ? 'Not Connected' : 'Connected' }}</p>
|
||||
<p>Sharing: <button @click="share" class="border bordercolor rounded-lg p-0.5">{{ userStore.user.value.share
|
||||
}}</button></p>
|
||||
<button @click="getMe" class="border bordercolor rounded-lg p-0.5"> Refresh
|
||||
</button>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useHeaderStore } from '@/stores/headerStore';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -9,7 +7,6 @@ function isActive(path: string) {
|
||||
return route.path === path ? 'bg-blue-500 text-white' : '';
|
||||
};
|
||||
|
||||
const headerStore = useHeaderStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useAudioStore } from '@/stores/audioStore';
|
||||
import { useAudio } from '@/composables/useAudio';
|
||||
|
||||
const audioStore = useAudioStore();
|
||||
const audioStore = useAudio();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -25,7 +24,7 @@ const audioStore = useAudioStore();
|
||||
<i class="relative p-36 fa-solid fa-play">
|
||||
|
||||
<img class="absolute top-4 left-0 bottom-0 right-0 bg-center bg-cover rounded-lg"
|
||||
:src="encodeURI(audioStore.bgimg + '?h=320&w=320')" :key="audioStore.bgimg" />
|
||||
:src="encodeURI(audioStore.bgimg.value + '?h=320&w=320')" :key="audioStore.bgimg.value" />
|
||||
</i>
|
||||
</div>
|
||||
|
||||
@@ -34,25 +33,25 @@ const audioStore = useAudioStore();
|
||||
<div>
|
||||
<div class="flex w-full justify-around">
|
||||
<i class="fa-solid fa-backward-step text-5xl self-center" @click="audioStore.togglePrev"></i>
|
||||
<i :class="[audioStore.isPlaying ? 'fa-circle-play' : 'fa-circle-pause']" class="fa-regular text-7xl "
|
||||
<i :class="[audioStore.isPlaying.value ? 'fa-circle-play' : 'fa-circle-pause']" class="fa-regular text-7xl "
|
||||
@click="audioStore.togglePlay"></i>
|
||||
<i class="fa-solid fa-forward-step text-5xl self-center" @click="audioStore.toggleNext"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-1 justify-around ml-4">
|
||||
<i @click="audioStore.toggleShuffle" :class="[audioStore.shuffle ? 'info' : '']"
|
||||
<i @click="audioStore.toggleShuffle" :class="[audioStore.shuffle.value ? 'info' : '']"
|
||||
class="fa-solid fa-shuffle"></i>
|
||||
|
||||
<div class="m-4 info flex-1 overflow-hidden">
|
||||
<p>{{ audioStore.title }}</p>
|
||||
<RouterLink :to="'search?a=' + audioStore.artist">
|
||||
<p>{{ audioStore.title.value }}</p>
|
||||
<RouterLink :to="'search?a=' + audioStore.artist.value">
|
||||
|
||||
{{ audioStore.artist }}
|
||||
{{ audioStore.artist.value }}
|
||||
|
||||
</RouterLink>
|
||||
</div>
|
||||
<div class="flex flex-col justify-between mb-4 mr-4">
|
||||
<i @click="audioStore.toggleRepeat" :class="[audioStore.repeat ? 'info' : '']"
|
||||
<i @click="audioStore.toggleRepeat" :class="[audioStore.repeat.value ? 'info' : '']"
|
||||
class="fa-solid fa-repeat"></i>
|
||||
<i @click="$router.go(-1);" class="fa-solid fa-arrow-down"></i>
|
||||
</div>
|
||||
@@ -60,11 +59,11 @@ const audioStore = useAudioStore();
|
||||
<div class="flex">
|
||||
<input
|
||||
class="appearance-none mx-4 flex-1 bg-yellow-200 bg-opacity-20 accent-yellow-600 rounded-lg outline-none slider "
|
||||
type="range" id="audio-slider" @change="audioStore.updateTime" max="100" :value="audioStore.percentDone">
|
||||
type="range" id="audio-slider" @change="audioStore.updateTime" max="100" :value="audioStore.percentDone.value">
|
||||
</div>
|
||||
<div class="flex justify-between mx-4">
|
||||
<span id="current-time" class="time">{{ audioStore.currentTime }}</span>
|
||||
<span id="duration" class="time ">{{ audioStore.duration }}</span>
|
||||
<span id="current-time" class="time">{{ audioStore.currentTime.value }}</span>
|
||||
<span id="duration" class="time ">{{ audioStore.duration.value }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import SongItem from '../components/SongItem.vue'
|
||||
|
||||
import type { Song, CollectionPreview } from '../script/types'
|
||||
import { type Song, type CollectionPreview, mapApiToSongs } 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';
|
||||
import { useAudio } from '@/composables/useAudio';
|
||||
import { useUser } from '@/composables/useUser';
|
||||
import { useApi } from '@/composables/useApi';
|
||||
|
||||
const userStore = useUser();
|
||||
const audioStore = useAudio();
|
||||
const { musicApi } = useApi();
|
||||
const api = musicApi()
|
||||
|
||||
const route = useRoute();
|
||||
const userStore = useUserStore();
|
||||
const audioStore = useAudioStore();
|
||||
|
||||
const songs = ref<Song[]>([]);
|
||||
const name = ref('name');
|
||||
@@ -23,19 +25,23 @@ 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}`;
|
||||
});
|
||||
try {
|
||||
const response = await api.musicBackendRecent(limit.value, offset.value);
|
||||
if (response.data.songs) {
|
||||
let newSongs = mapApiToSongs(response.data.songs);
|
||||
|
||||
offset.value += limit.value;
|
||||
console.log(data)
|
||||
songs.value = [...songs.value, ...data];
|
||||
songs.value = [...songs.value, ...newSongs];
|
||||
|
||||
console.log(offset.value)
|
||||
|
||||
isLoading.value = false;
|
||||
audioStore.setCollection(songs.value);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load songs:', error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,124 +1,128 @@
|
||||
<script setup lang="ts">
|
||||
import type { Song, CollectionPreview } from '../script/types'
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { mapApiToSongs, type Song } from '../script/types'
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import ActiveSearchList from '../components/ActiveSearchList.vue'
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import SongItem from '../components/SongItem.vue'
|
||||
import { useAudioStore } from '@/stores/audioStore';
|
||||
import { useAudio } from '@/composables/useAudio'
|
||||
import { useUser } from '@/composables/useUser'
|
||||
import { MusicBackendApi } from '@/generated'
|
||||
import { useApi } from '@/composables/useApi'
|
||||
|
||||
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);
|
||||
const searchTerm = ref('');
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const audioStore = useAudio()
|
||||
const userStore = useUser()
|
||||
const { musicApi } = useApi()
|
||||
const api = musicApi()
|
||||
|
||||
const activesongs = ref<Song[]>([])
|
||||
const songs = ref<Song[]>([])
|
||||
const artists = ref<string[]>([])
|
||||
const showSearch = ref(false)
|
||||
const searchTerm = ref('')
|
||||
|
||||
async function fetchActiveSearch(term: string) {
|
||||
const response = await api.musicBackendSearch(term);
|
||||
|
||||
const songData = mapApiToSongs(response.data.songs)
|
||||
|
||||
songData.forEach((song: Song) => {
|
||||
song.previewimage = `${userStore.baseUrl.value}/api/v1/images/${song.previewimage}`
|
||||
song.url = `${userStore.baseUrl.value}/api/v1/audio/${song.url}`
|
||||
})
|
||||
|
||||
activesongs.value = songData
|
||||
|
||||
if (response.data.artist) artists.value = [response.data.artist]
|
||||
audioStore.setCollection(songData)
|
||||
showSearch.value = true
|
||||
searchTerm.value = term
|
||||
router.replace({ query: { s: term } })
|
||||
}
|
||||
|
||||
async function fetchSearchArtist(artist: string) {
|
||||
const data = await musicApi.MusicBackend_SearchArtists(artist)
|
||||
|
||||
data.forEach((song: Song) => {
|
||||
song.previewimage = `${userStore.baseUrl.value}/api/v1/images/${song.previewimage}`
|
||||
song.url = `${userStore.baseUrl.value}/api/v1/audio/${song.url}`
|
||||
})
|
||||
|
||||
songs.value = data
|
||||
showSearch.value = false
|
||||
}
|
||||
|
||||
async function emptySearch() {
|
||||
activesongs.value = []
|
||||
artists.value = []
|
||||
songs.value = []
|
||||
showSearch.value = false
|
||||
searchTerm.value = ''
|
||||
router.replace({ query: {} })
|
||||
}
|
||||
|
||||
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 } });
|
||||
searchTerm.value = 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;
|
||||
router.push({ query: { s: target.value } });
|
||||
|
||||
}
|
||||
});
|
||||
container.addEventListener('enter', async (event: Event) => {
|
||||
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.value != undefined && target.value != "") {
|
||||
showSearch.value = false
|
||||
const data = await userStore.fetchActiveSearch(target.value)
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
if (route.query.a) {
|
||||
await fetchSearchArtist(route.query.a as string)
|
||||
}
|
||||
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;
|
||||
if (route.query.s) {
|
||||
await fetchActiveSearch(route.query.s as string)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function emptySearch() {
|
||||
const container = document.querySelector('.search') as HTMLInputElement;
|
||||
// Watch for artist query changes
|
||||
watch(() => route.query.a, async (newArtist) => {
|
||||
if (newArtist) {
|
||||
await fetchSearchArtist(newArtist as string)
|
||||
} else {
|
||||
songs.value = []
|
||||
}
|
||||
})
|
||||
|
||||
container.value = "";
|
||||
container.dispatchEvent(new Event('input'))
|
||||
songs.value = [];
|
||||
artists.value = [];
|
||||
|
||||
}
|
||||
watch(() => route.query.a, async (newQuery) => {
|
||||
|
||||
await loadartistifexist();
|
||||
|
||||
});
|
||||
// Search input model
|
||||
const searchInput = ref(searchTerm.value)
|
||||
|
||||
watch(searchInput, async (val) => {
|
||||
if (val && val.trim() !== '') {
|
||||
await fetchActiveSearch(val)
|
||||
} else {
|
||||
showSearch.value = false
|
||||
activesongs.value = []
|
||||
artists.value = []
|
||||
router.replace({ query: {} })
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header>
|
||||
<div class="wrapper">
|
||||
<nav class="flex justify-start my-2 mx-1 space-x-1">
|
||||
<RouterLink class="p-1 rounded-full backdrop--light shadow-xl" to="/"><i class="fa-solid fa-arrow-left"></i>
|
||||
<RouterLink class="p-1 rounded-full backdrop--light shadow-xl" to="/">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</RouterLink>
|
||||
<h1 class="absolute left-0 right-0 text-center"> Search </h1>
|
||||
<h1 class="absolute left-0 right-0 text-center">Search</h1>
|
||||
</nav>
|
||||
<hr>
|
||||
<hr />
|
||||
</div>
|
||||
</header>
|
||||
<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 bordercolor accent-pink-800 bg-yellow-300 bg-opacity-20 rounded-lg m-2 p-2" />
|
||||
|
||||
<div class="absolute h-16 right-4 flex flex-col justify-center">
|
||||
<i @click="emptySearch" class="far fa-times-circle opacity-50"></i>
|
||||
<main class="flex flex-col flex-1 w-full h-full overflow-scroll">
|
||||
<div class="relative">
|
||||
<input
|
||||
v-model="searchInput"
|
||||
placeholder="Type to Search..."
|
||||
class="flex-1 max-h-12 search border bordercolor accent-pink-800 bg-yellow-300 bg-opacity-20 rounded-lg m-2 p-2"
|
||||
/>
|
||||
<div class="absolute h-16 right-4 flex flex-col justify-center cursor-pointer" @click="emptySearch">
|
||||
<i class="far fa-times-circle opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<div v-if="showSearch" class="absolute w-full text-center search-recommendations z-20">
|
||||
<ActiveSearchList :songs="activesongs" :artist="artists" :search="searchTerm" />
|
||||
</div>
|
||||
<SongItem v-for="(song, index) in songs" :key="index" :song="song" />
|
||||
|
||||
Reference in New Issue
Block a user