mirror of
https://github.com/JuLi0n21/pwa-player.git
synced 2026-04-19 23:40:05 +00:00
fix cloudflare fr?
This commit is contained in:
@@ -50,7 +50,7 @@ onUnmounted(() => {
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div v-if="screenInfo.isSmall" class="flex flex-col h-screen max-h-screen text-xl wrapper info">
|
||||
<div v-if="screenInfo.isSmall" class="flex flex-col h-screen max-h-screen overflow-y-auto text-xl wrapper info">
|
||||
<RouterView />
|
||||
<NowPlaying v-show="showNowPlaying" />
|
||||
<Footer />
|
||||
@@ -58,7 +58,7 @@ onUnmounted(() => {
|
||||
|
||||
<div v-else class="flex flex-col h-screen max-h-screen text-xl wrapper info">
|
||||
<main class="flex flex-1 w-full h-full overflow-y-hidden">
|
||||
<aside class="bg-primary p-4 w-1/12 overflow-y-scroll">
|
||||
<aside class="bg-primary p-4 w-1/12 overflow-y-auto">
|
||||
<HistoryView />
|
||||
</aside>
|
||||
|
||||
@@ -66,7 +66,7 @@ onUnmounted(() => {
|
||||
<RouterView />
|
||||
</section>
|
||||
|
||||
<section class="flex flex-col w-1/5 overflow-y-scroll">
|
||||
<section class="flex flex-col w-1/5 overflow-y-auto">
|
||||
<NowPlayingView />
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -3,8 +3,9 @@ import type { Song, CollectionPreview } from "../script/types";
|
||||
import { useAudio } from "@/composables/useAudio";
|
||||
import { ref } from "vue";
|
||||
import { RouterLink } from "vue-router";
|
||||
|
||||
import { useUser } from "@/composables/useUser";
|
||||
const audioStore = useAudio();
|
||||
const userStore = useUser();
|
||||
|
||||
const props = defineProps<{
|
||||
songs: Song[];
|
||||
@@ -39,7 +40,7 @@ function highlightText(text: string, searchterm: string) {
|
||||
<ul>
|
||||
<li v-for="(song, index) in props.songs" :key="index" class="rounded-lg">
|
||||
<button @click="update(song.hash)" class="flex">
|
||||
<img :src="encodeURI(song.previewimage + '?h=120&w=120')" class="w-12 h-12" />
|
||||
<img :src="encodeURI(`${userStore.cloudflareUrl.value}/${song.previewimage ? song.previewimage + '?h=120&w=120' : '/default-bg.png'}`)" class="w-12 h-12" />
|
||||
<p class="ml-2 overflow-hidden text-ellipsis text-nowrap">
|
||||
<span v-html="highlightText(song.name, search)"></span> -
|
||||
<span v-html="highlightText(song.artist, props.search)"></span>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type { CollectionPreview } from "@/script/types";
|
||||
import { useUser } from "@/composables/useUser";
|
||||
|
||||
const userStore = useUser();
|
||||
const props = defineProps<{ collection: CollectionPreview }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterLink :to="'/collection/' + props.collection.index">
|
||||
<div class="flex border rounded-lg bordercolor">
|
||||
<img class="m-2 rounded-lg w-20 h-20" :src="props.collection.previewimage" loading="lazy" />
|
||||
<img class="m-2 rounded-lg w-20 h-20" :src="encodeURI(`${userStore.cloudflareUrl.value}${props.collection.previewimage}`)" loading="lazy" />
|
||||
<div class="flex flex-col">
|
||||
<h3 class="self-start info">{{ props.collection.name }}</h3>
|
||||
<h5 class="self-start text-sm info">{{ props.collection.length }} Songs</h5>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { useAudio } from "@/composables/useAudio";
|
||||
import { onMounted, computed } from "vue";
|
||||
import { useUser } from "@/composables/useUser";
|
||||
|
||||
const audioStore = useAudio();
|
||||
const userStore = useUser();
|
||||
|
||||
const title = computed(() => audioStore.currentSong.value?.name || "Unknown Title");
|
||||
const artist = computed(() => audioStore.currentSong.value?.artist || "Unknown Artist");
|
||||
@@ -16,26 +18,26 @@ onMounted(() => {
|
||||
<template>
|
||||
<div>
|
||||
<hr />
|
||||
<div class="relative wrapper p-1 action">
|
||||
<div class="relative p-1 wrapper action">
|
||||
<img
|
||||
:src="encodeURI(bgimg + '?h=150&w=400')"
|
||||
class="w-full absolute top-0 left-0 right-0 h-full"
|
||||
:src="encodeURI(`${userStore.cloudflareUrl.value}${bgimg}?h=150&w=400`)"
|
||||
class="top-0 right-0 left-0 absolute w-full h-full"
|
||||
:style="{ filter: 'blur(2px)', opacity: '0.5' }"
|
||||
alt="Background Image"
|
||||
/>
|
||||
|
||||
<nav class="relative flex-col z-10">
|
||||
<nav class="z-10 relative flex-col">
|
||||
<div class="flex justify-between">
|
||||
<RouterLink to="/nowplaying" class="grow overflow-hidden">
|
||||
<p class="relative text-sm text-left font-bold info overflow-hidden text-ellipsis text-nowrap">
|
||||
<RouterLink to="/nowplaying" class="overflow-hidden grow">
|
||||
<p class="relative overflow-hidden font-bold text-sm text-left text-ellipsis text-nowrap info">
|
||||
{{ title }}
|
||||
</p>
|
||||
|
||||
<p class="relative text-sm text-left font-bold info text-nowrap">
|
||||
<p class="relative font-bold text-sm text-left text-nowrap info">
|
||||
{{ artist }}
|
||||
</p>
|
||||
</RouterLink>
|
||||
<div class="flex flex-col text-center justify-center px-2" @click="audioStore.togglePlay">
|
||||
<div class="flex flex-col justify-center px-2 text-center" @click="audioStore.togglePlay">
|
||||
<i
|
||||
:class="[audioStore.isPlaying.value ? ' fa-circle-pause' : 'fa-circle-play']"
|
||||
class="text-3xl fa-regular"
|
||||
@@ -43,9 +45,9 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full bg-gray-200 rounded-full h-0.5 dark:bg-gray-700">
|
||||
<div class="bg-gray-200 dark:bg-gray-700 rounded-full w-full h-0.5">
|
||||
<div
|
||||
class="bg-blue-600 h-0.5 rounded-full dark:bg-yellow-500"
|
||||
class="bg-blue-600 dark:bg-yellow-500 rounded-full h-0.5"
|
||||
:style="{ width: audioStore.percentDone.value + '%' }"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useAudio } from "@/composables/useAudio";
|
||||
import { useUser } from "@/composables/useUser";
|
||||
import type { Song } from "@/script/types";
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -9,7 +10,7 @@ const props = defineProps<{
|
||||
border?: string;
|
||||
}>();
|
||||
const audioStore = useAudio();
|
||||
|
||||
const userStore = useUser();
|
||||
function updateSong() {
|
||||
let updated = props.song;
|
||||
audioStore.setSong(updated);
|
||||
@@ -20,8 +21,7 @@ function updateSong() {
|
||||
<div @click="updateSong" :style="{ borderColor: border }" class="flex m-1 border rounded-lg md:text-xl bordercolor">
|
||||
<img
|
||||
class="m-1 rounded-lg w-14 md:w-24 h-14 md:h-24"
|
||||
:src="encodeURI(props.song?.previewimage ? props.song?.previewimage + '?h=56&w=56' : '/default-bg.png')"
|
||||
loading="lazy"
|
||||
:src="props.song?.previewimage ? encodeURI(`${userStore.cloudflareUrl.value}${props.song.previewimage}?h=56&w=56`) : '/default-bg.png'" loading="lazy"
|
||||
/>
|
||||
<div class="flex flex-col overflow-hidden text-left">
|
||||
<p :style="{ color: info }" class="overflow-hidden text-base text-ellipsis text-nowrap info">
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { ref, onMounted } from "vue";
|
||||
import { mapApiToSongs, type Song } from "@/script/types";
|
||||
import { useApi } from "./useApi";
|
||||
import { useUser } from "./useUser";
|
||||
|
||||
let audioInstance: ReturnType<typeof createAudio> | null = null;
|
||||
|
||||
function createAudio() {
|
||||
const { musicApi } = useApi();
|
||||
const userStore = useUser();
|
||||
|
||||
const audioElement = document.createElement("audio");
|
||||
audioElement.setAttribute("id", "global-audio");
|
||||
@@ -46,7 +48,7 @@ function createAudio() {
|
||||
map.set(song.hash, song);
|
||||
|
||||
audioElement.pause();
|
||||
audioElement.src = song.url;
|
||||
audioElement.src = userStore.cloudflareUrl.value + "/" + song.url;
|
||||
audioElement.addEventListener("canplaythrough", () => audioElement.play().catch(console.error), { once: true });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Apiv1Song, v1CollectionPreview, v1Collection } from "@/generated";
|
||||
import type { Apiv1Song, V1CollectionPreview, V1CollectionResponse } from "@/generated";
|
||||
|
||||
export type Song = {
|
||||
hash: string;
|
||||
@@ -9,20 +9,16 @@ export type Song = {
|
||||
previewimage: string;
|
||||
mapper: string;
|
||||
};
|
||||
|
||||
const basePath = import.meta.env.BACKEND_URL || "http://localhost:8080";
|
||||
|
||||
export function mapToSong(apiSong: Apiv1Song): Song {
|
||||
const image = apiSong.image;
|
||||
const imageIsMissing = !image || image === "404.png";
|
||||
|
||||
return {
|
||||
hash: apiSong.md5Hash,
|
||||
name: apiSong.title,
|
||||
artist: apiSong.artist,
|
||||
length: Number(apiSong.totalTime),
|
||||
url: `${basePath}/api/v1/audio/${btoa(apiSong.folder + "/" + apiSong.audio).replace(/=+$/, "")}`,
|
||||
previewimage: imageIsMissing ? "/404.gif" : `${basePath}/api/v1/image/${btoa(image).replace(/=+$/, "")}`,
|
||||
url: `/api/v1/audio/${btoa(apiSong.folder + "/" + apiSong.audio).replace(/=+$/, "")}`,
|
||||
previewimage: image ? `/api/v1/image/${btoa(image).replace(/=+$/, "")}` : "",
|
||||
mapper: apiSong.creator,
|
||||
};
|
||||
}
|
||||
@@ -40,7 +36,7 @@ export type Collection = {
|
||||
songs: Song[];
|
||||
};
|
||||
|
||||
export function mapApiToCollection(coll: v1Collection): Collection {
|
||||
export function mapApiToCollection(coll: V1CollectionResponse): Collection {
|
||||
return {
|
||||
name: coll.name,
|
||||
items: coll.items,
|
||||
@@ -48,15 +44,14 @@ export function mapApiToCollection(coll: v1Collection): Collection {
|
||||
};
|
||||
}
|
||||
|
||||
export function mapToCollectionPreview(apiCollection: v1CollectionPreview, index: number): CollectionPreview {
|
||||
export function mapToCollectionPreview(apiCollection: V1CollectionPreview, index: number): CollectionPreview {
|
||||
const image = apiCollection.image;
|
||||
const imageIsMissing = !image || image === "404.png";
|
||||
|
||||
return {
|
||||
index: index,
|
||||
name: apiCollection.name,
|
||||
length: apiCollection.items,
|
||||
previewimage: imageIsMissing ? "/404.gif" : `${basePath}/api/v1/image/${btoa(image).replace(/=+$/, "")}`,
|
||||
previewimage: image ? `/api/v1/image/${btoa(image).replace(/=+$/, "")}` : "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,6 +67,6 @@ export function mapApiToSongs(apiSongs: Apiv1Song[]): Song[] {
|
||||
return apiSongs.map(mapToSong);
|
||||
}
|
||||
|
||||
export function mapApiToCollectionPreview(apiCollections: v1CollectionPreview[], offset: number): CollectionPreview[] {
|
||||
export function mapApiToCollectionPreview(apiCollections: V1CollectionPreview[], offset: number): CollectionPreview[] {
|
||||
return apiCollections.map((c, i) => mapToCollectionPreview(c, i + offset));
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useAudio } from "@/composables/useAudio";
|
||||
import { useUser } from "@/composables/useUser";
|
||||
|
||||
const audioStore = useAudio();
|
||||
|
||||
const userStore = useUser();
|
||||
const title = computed(() => audioStore.currentSong.value?.name || "Unknown Title");
|
||||
const artist = computed(() => audioStore.currentSong.value?.artist || "Unknown Artist");
|
||||
const bgimg = computed(() => audioStore.currentSong.value?.previewimage || "/default-bg.jpg");
|
||||
</script>
|
||||
const bgimg = computed(() => {
|
||||
const preview = audioStore.currentSong.value?.previewimage;
|
||||
return preview
|
||||
? encodeURI(`${userStore.cloudflareUrl.value}${preview}`)
|
||||
: "/default-bg.jpg";
|
||||
});</script>
|
||||
|
||||
<template>
|
||||
<header>
|
||||
@@ -29,7 +34,7 @@ const bgimg = computed(() => audioStore.currentSong.value?.previewimage || "/def
|
||||
<div class="relative w-full aspect-square">
|
||||
<img
|
||||
class="absolute inset-0 shadow-lg rounded-lg w-full h-full object-cover"
|
||||
:src="encodeURI(bgimg + '?h=320&w=320')"
|
||||
:src="encodeURI(`${bgimg}?h=320&w=320`)"
|
||||
:key="bgimg"
|
||||
alt="Album Art"
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,6 @@ import SongItem from "../components/SongItem.vue";
|
||||
|
||||
import { type Song, type CollectionPreview, mapApiToSongs } from "../script/types";
|
||||
import { ref, onMounted, nextTick } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useAudio } from "@/composables/useAudio";
|
||||
import { useUser } from "@/composables/useUser";
|
||||
import { useApi } from "@/composables/useApi";
|
||||
|
||||
Reference in New Issue
Block a user