feat(library): add strategy parameter for item fetching and update filter preview

This commit is contained in:
2026-03-12 03:24:32 +01:00
parent 6d1bed2ecb
commit e5a9b99b14
7 changed files with 46 additions and 13 deletions

View File

@@ -402,8 +402,8 @@ function AlgorithmicFilterEditor({
</Field>
</div>
{/* Preview — snapshot of current filter, only fetches on explicit click */}
<FilterPreview filter={content.filter} />
{/* Preview — snapshot of current filter+strategy, only fetches on explicit click */}
<FilterPreview filter={content.filter} strategy={content.strategy} />
</div>
);
}

View File

@@ -7,6 +7,7 @@ import type { MediaFilter, LibraryItemResponse } from "@/lib/types";
interface FilterPreviewProps {
filter: MediaFilter;
strategy?: string;
}
function fmtDuration(secs: number): string {
@@ -31,17 +32,25 @@ function ItemRow({ item }: { item: LibraryItemResponse }) {
);
}
export function FilterPreview({ filter }: FilterPreviewProps) {
// Snapshot of filter at the moment "Preview" was clicked, so edits to the
// filter don't silently re-fetch while the user is still configuring.
const [snapshot, setSnapshot] = useState<MediaFilter | null>(null);
type Snapshot = { filter: MediaFilter; strategy?: string };
const { data: items, isFetching, isError } = useLibraryItems(snapshot, !!snapshot);
export function FilterPreview({ filter, strategy }: FilterPreviewProps) {
// Capture both filter and strategy at click time so edits don't silently
// re-fetch while the user is still configuring the block.
const [snapshot, setSnapshot] = useState<Snapshot | null>(null);
const handlePreview = () => setSnapshot({ ...filter });
const { data: items, isFetching, isError } = useLibraryItems(
snapshot?.filter ?? null,
!!snapshot,
snapshot?.strategy,
);
const handlePreview = () => setSnapshot({ filter: { ...filter }, strategy });
const filterChanged =
snapshot !== null && JSON.stringify(snapshot) !== JSON.stringify(filter);
snapshot !== null &&
(JSON.stringify(snapshot.filter) !== JSON.stringify(filter) ||
snapshot.strategy !== strategy);
return (
<div className="space-y-1">
@@ -67,6 +76,7 @@ export function FilterPreview({ filter }: FilterPreviewProps) {
<div className="rounded-md border border-zinc-700/60 bg-zinc-800/30 px-3 py-1">
<p className="pb-1 pt-1.5 text-[11px] font-medium uppercase tracking-wider text-zinc-600">
{items.length === 30 ? "First 30 matches" : `${items.length} match${items.length !== 1 ? "es" : ""}`}
{strategy === "random" ? " · shuffled" : strategy === "best_fit" ? " · longest first" : ""}
</p>
{items.length === 0 ? (
<p className="py-1.5 text-xs text-zinc-600">No items match this filter.</p>