some other small improvements

This commit is contained in:
2026-03-12 22:48:35 +01:00
parent ab0038402e
commit 894799e34d
12 changed files with 349 additions and 160 deletions

View File

@@ -1,9 +1,8 @@
<script setup lang="ts">
import type { Song, CollectionPreview } from "../script/types";
import type { Song } 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();
@@ -13,48 +12,72 @@ const props = defineProps<{
search: string;
}>();
function update(hash: string) {
audioStore.setSong(props.songs[props.songs.findIndex((s) => s.hash == hash)]);
function playSong(hash: string) {
const selected = props.songs.find((s) => s.hash === hash);
if (selected) {
audioStore.setSong(selected);
}
}
function highlightText(text: string, searchterm: string) {
if (!searchterm) return text;
const regex = new RegExp(`(${searchterm})`, "gi");
return text.replace(regex, '<span style="color: yellow;">$1</span>');
return text.replace(regex, '<span class="font-bold text-yellow-400">$1</span>');
}
</script>
<template>
<div class="border rounded-lg w-full h-full overflow-scroll overflow-x-hidden text-xs bordercolor bg">
<div v-if="props.artist && props.artist.length > 0" class="border bordercolor">
<h2 class="text-2xl action">Artists</h2>
<ul>
<li v-for="(artist, index) in props.artist" :key="index" class="rounded-lg">
<RouterLink class="flex" :to="'/search?a=' + artist" v-html="highlightText(artist, props.search)">
<div class="w-full h-full text-xs">
<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>
<ul class="space-y-1 px-2">
<li v-for="(artist, index) in props.artist" :key="index">
<RouterLink
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"
>
<div class="flex justify-center items-center bg-yellow-500/20 mr-3 rounded-full w-10 h-10">
<i class="text-yellow-500 fa-solid fa-user"></i>
</div>
<span class="text-base info" v-html="highlightText(artist, props.search)"></span>
</RouterLink>
</li>
</ul>
</div>
<div v-if="props.songs && props.songs.length > 0" class="border bordercolor">
<h2 class="text-2xl action">Songs</h2>
<ul>
<li v-for="(song, index) in props.songs" :key="index" class="rounded-lg">
<button @click="update(song.hash)" class="flex">
<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>
<ul class="space-y-1 px-2 pb-20"> <li v-for="(song, index) in props.songs" :key="index">
<button
@click="playSong(song.hash)"
class="flex items-center p-2 rounded-xl w-full text-left transition-colors"
>
<img
:src="
encodeURI(
`${userStore.cloudflareUrl.value}/${song.previewimage ? song.previewimage + '?h=120&w=120' : '/default-bg.png'}`,
)
"
class="w-12 h-12"
:src="song.previewimage
? `${userStore.cloudflareUrl.value}${song.previewimage}?h=120&w=120`
: '/default-bg.png'"
class="rounded-lg w-12 h-12 object-cover shrink-0"
loading="lazy"
/>
<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>
</p>
<div class="flex-1 ml-3 overflow-hidden">
<p class="text-base truncate info">
<span v-html="highlightText(song.name, search)"></span>
</p>
<p class="opacity-60 text-sm truncate action">
<span v-html="highlightText(song.artist, props.search)"></span>
</p>
</div>
<i class="opacity-0 group-hover:opacity-100 ml-2 pr-2 transition-opacity fa-solid fa-play"></i>
</button>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
:deep(.text-yellow-400) {
color: #facc15;
}
</style>