feat(library): add media library browsing functionality
- Introduced new `library` module in the API routes to handle media library requests. - Enhanced `AppState` to include a media provider for library interactions. - Defined new `IMediaProvider` trait methods for listing collections, series, and genres. - Implemented Jellyfin media provider methods for fetching collections and series. - Added frontend components for selecting series and displaying filter previews. - Created hooks for fetching collections, series, and genres from the library. - Updated media filter to support series name and search term. - Enhanced API client to handle new library-related endpoints.
This commit is contained in:
62
k-tv-frontend/hooks/use-library.ts
Normal file
62
k-tv-frontend/hooks/use-library.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { api } from "@/lib/api";
|
||||
import { useAuthContext } from "@/context/auth-context";
|
||||
import type { MediaFilter } from "@/lib/types";
|
||||
|
||||
const STALE = 10 * 60 * 1000; // 10 min — library metadata rarely changes in a session
|
||||
|
||||
/** List top-level collections (Jellyfin libraries, Plex sections, etc.) */
|
||||
export function useCollections() {
|
||||
const { token } = useAuthContext();
|
||||
return useQuery({
|
||||
queryKey: ["library", "collections"],
|
||||
queryFn: () => api.library.collections(token!),
|
||||
enabled: !!token,
|
||||
staleTime: STALE,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* List TV series, optionally scoped to a collection.
|
||||
* All series are loaded upfront so the series picker can filter client-side
|
||||
* without a request per keystroke.
|
||||
*/
|
||||
export function useSeries(collectionId?: string) {
|
||||
const { token } = useAuthContext();
|
||||
return useQuery({
|
||||
queryKey: ["library", "series", collectionId ?? null],
|
||||
queryFn: () => api.library.series(token!, collectionId),
|
||||
enabled: !!token,
|
||||
staleTime: STALE,
|
||||
});
|
||||
}
|
||||
|
||||
/** List available genres, optionally scoped to a content type. */
|
||||
export function useGenres(contentType?: string) {
|
||||
const { token } = useAuthContext();
|
||||
return useQuery({
|
||||
queryKey: ["library", "genres", contentType ?? null],
|
||||
queryFn: () => api.library.genres(token!, contentType),
|
||||
enabled: !!token,
|
||||
staleTime: STALE,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch items matching a filter for the block editor's "Preview results" panel.
|
||||
* Pass `enabled: false` until the user explicitly requests a preview.
|
||||
*/
|
||||
export function useLibraryItems(
|
||||
filter: Pick<MediaFilter, "content_type" | "series_name" | "collections" | "search_term" | "genres"> | null,
|
||||
enabled: boolean,
|
||||
) {
|
||||
const { token } = useAuthContext();
|
||||
return useQuery({
|
||||
queryKey: ["library", "items", filter],
|
||||
queryFn: () => api.library.items(token!, filter!, 30),
|
||||
enabled: !!token && enabled && !!filter,
|
||||
staleTime: 2 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user