feat(tracks): search + lazy load images

This commit is contained in:
2024-11-28 05:41:47 +01:00
parent 30e7b758ad
commit c89073e025
7 changed files with 103 additions and 10 deletions

View File

@@ -68,9 +68,8 @@
method="POST"
use:enhance={submitPlayerAction}
>
{#each player.queue as track, i (track.hash)}
{#each player.queue as track, i}
<button
animate:flip={{ duration: 100 }}
type="submit"
class="flex flex-row items-center gap-2 rounded-lg px-3 py-2 transition-all hover:bg-secondary"
formaction="/player?/skip-to-queue-index&index={i}"

View File

@@ -6,12 +6,15 @@
import type { SubmitFunction } from '../../../routes/tracks/[hash]/$types';
import type { Track } from '$lib/proto/library';
import * as ContextMenu from '$lib/components/ui/context-menu';
import type { Action } from 'svelte/action';
interface Props {
track: Track;
hideCover?: boolean;
action: Action;
}
let { track }: Props = $props();
let { track, action, hideCover = false }: Props = $props();
let isOpen = $state(false);
@@ -58,15 +61,22 @@
method="POST"
action="/tracks/{track.hash}?/play"
use:enhance={submitPlayTrack}
use:action
data-track-hash={track.hash}
>
<ContextMenu.Root bind:open={isOpen}>
<ContextMenu.Trigger>
<div class="relative">
<button type="submit" class="relative overflow-hidden rounded-lg">
<div class="relative aspect-square w-full">
<button
type="submit"
class="relative aspect-square h-full w-full overflow-hidden rounded-lg"
>
<img
class="aspect-square w-auto transition-all duration-150 hover:scale-105 hover:saturate-150"
src={getCoverUrl(track.hash)}
class="aspect-square h-full w-full transform-gpu transition-all duration-150 hover:scale-105 hover:saturate-150"
src={hideCover ? undefined : getCoverUrl(track.hash)}
alt={track.name}
width="640"
height="640"
/>
</button>

25
src/lib/search.svelte.ts Normal file
View File

@@ -0,0 +1,25 @@
import { Fzf } from 'fzf';
import type { Track } from './proto/library';
import { getContext, setContext } from 'svelte';
class SearchState {
input = $state('');
filterTracks(tracks: Track[]) {
const fzf = new Fzf(tracks, {
selector: (t) => `${t.name} ${t.artistName}`,
sort: true,
});
return fzf.find(this.input);
}
}
const SEARCH_KEY = Symbol('SEARCH');
export function setSearchState() {
return setContext(SEARCH_KEY, new SearchState());
}
export function getSearchState() {
return getContext<ReturnType<typeof setSearchState>>(SEARCH_KEY);
}