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