From 1a4bde961877d68d6d49578d66e921d3d7cf97ad Mon Sep 17 00:00:00 2001 From: 409 Date: Fri, 29 Nov 2024 04:28:26 +0100 Subject: [PATCH] feat(tracks): search --- bun.lockb | Bin 97782 -> 97790 bytes package.json | 2 +- src/lib/components/groove/TrackListing.svelte | 13 ++++----- src/lib/search.svelte.ts | 25 +++++++++++++----- src/routes/tracks/+page.svelte | 15 ++++++++--- 5 files changed, 37 insertions(+), 18 deletions(-) diff --git a/bun.lockb b/bun.lockb index 44fe1c3b4e0624574ab81953c3c836951933deb8..3d79beb82f025131bbc2932ea86539b56dfbbcac 100755 GIT binary patch delta 7457 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 delta 7451 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 AO8@`> diff --git a/package.json b/package.json index 71d7de2..5f3d177 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@protobuf-ts/grpcweb-transport": "^2.9.4", "@protobuf-ts/plugin": "^2.9.4", "dayjs": "^1.11.13", - "fzf": "^0.5.2", + "fuse.js": "^7.0.0", "mode-watcher": "^0.5.0" } } diff --git a/src/lib/components/groove/TrackListing.svelte b/src/lib/components/groove/TrackListing.svelte index 7fdd6c7..8caceb8 100644 --- a/src/lib/components/groove/TrackListing.svelte +++ b/src/lib/components/groove/TrackListing.svelte @@ -1,7 +1,7 @@ -
oncontextmenu?.(e, track.hash)} -> +
-
+

{track.name}

diff --git a/src/lib/search.svelte.ts b/src/lib/search.svelte.ts index 35d0a25..52e921d 100644 --- a/src/lib/search.svelte.ts +++ b/src/lib/search.svelte.ts @@ -1,16 +1,29 @@ -import { Fzf } from 'fzf'; +import Fuse from 'fuse.js'; import type { Track } from './proto/library'; import { getContext, setContext } from 'svelte'; class SearchState { input = $state(''); + #fuse: Fuse | null = null; - filterTracks(tracks: Track[]) { - const fzf = new Fzf(tracks, { - selector: (t) => `${t.name} ${t.artistName}`, - sort: true + setTracks(tracks: Track[]) { + this.#fuse = new Fuse(tracks, { + keys: ['name', 'artistName'], + shouldSort: true, + includeScore: true, + threshold: 0.2, + findAllMatches: true }); - return fzf.find(this.input); + } + + filterTracks() { + if (this.input.length < 1 || !this.#fuse) { + return; + } + + const results = this.#fuse.search(this.input); + + return results.map((r) => r.item); } } diff --git a/src/routes/tracks/+page.svelte b/src/routes/tracks/+page.svelte index 1002c37..b2cf2f3 100644 --- a/src/routes/tracks/+page.svelte +++ b/src/routes/tracks/+page.svelte @@ -8,15 +8,22 @@ import Music2 from 'virtual:icons/lucide/music-2'; import ListMusic from 'virtual:icons/lucide/list-music'; import ListEnd from 'virtual:icons/lucide/list-end'; + import { getSearchState } from '$lib/search.svelte'; interface Props { data: PageServerData; } - const player = getPlayerState(); - let { data }: Props = $props(); + const player = getPlayerState(); + const search = getSearchState(); + + $effect(() => { + console.log('set tracks'); + search.setTracks(data.tracks); + }); + let contextMenuTarget = $state(null); const submitPlayTrack: SubmitFunction = async () => { @@ -53,6 +60,8 @@ function contextMenuItemClicked(e: MouseEvent) { e.stopPropagation(); } + + let filteredTracks = $derived(search.filterTracks());
- {#each data.tracks as track} + {#each filteredTracks ?? data.tracks as track}